Alerting: deactivate an Alertmanager configuration (#36794)

* Alerting: deactivate an Alertmanager configuration

Implement DELETE /api/alertmanager/grafana/config/api/v1/alerts
by storing the default configuration which stops existing cnfiguration
from being in use.

* Apply suggestions from code review
This commit is contained in:
Sofia Papagiannaki
2021-07-16 20:07:31 +03:00
committed by GitHub
parent f4f2c197ae
commit afe6e793ff
4 changed files with 65 additions and 2 deletions
+1
View File
@@ -25,6 +25,7 @@ var timeNow = time.Now
type Alertmanager interface {
// Configuration
SaveAndApplyConfig(config *apimodels.PostableUserConfig) error
SaveAndApplyDefaultConfig() error
GetStatus() apimodels.GettableStatus
// Silences
+9 -2
View File
@@ -45,8 +45,15 @@ func (srv AlertmanagerSrv) RouteCreateSilence(c *models.ReqContext, postableSile
}
func (srv AlertmanagerSrv) RouteDeleteAlertingConfig(c *models.ReqContext) response.Response {
// not implemented
return NotImplementedResp
if !c.HasUserRole(models.ROLE_EDITOR) {
return ErrResp(http.StatusForbidden, errors.New("permission denied"), "")
}
if err := srv.am.SaveAndApplyDefaultConfig(); err != nil {
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"})
}
func (srv AlertmanagerSrv) RouteDeleteSilence(c *models.ReqContext) response.Response {
@@ -201,6 +201,37 @@ func (am *Alertmanager) StopAndWait() error {
return nil
}
// SaveAndApplyDefaultConfig saves the default configuration the database and applies the configuration to the Alertmanager.
// It rollbacks the save if we fail to apply the configuration.
func (am *Alertmanager) SaveAndApplyDefaultConfig() error {
am.reloadConfigMtx.Lock()
defer am.reloadConfigMtx.Unlock()
cmd := &ngmodels.SaveAlertmanagerConfigurationCmd{
AlertmanagerConfiguration: alertmanagerDefaultConfiguration,
Default: true,
ConfigurationVersion: fmt.Sprintf("v%d", ngmodels.AlertConfigurationVersion),
}
cfg, err := Load([]byte(alertmanagerDefaultConfiguration))
if err != nil {
return err
}
err = am.Store.SaveAlertmanagerConfigurationWithCallback(cmd, func() error {
if err := am.applyConfig(cfg, []byte(alertmanagerDefaultConfiguration)); err != nil {
return err
}
return nil
})
if err != nil {
return err
}
am.Metrics.ActiveConfigurations.Set(1)
return nil
}
// SaveAndApplyConfig saves the configuration the database and applies the configuration to the Alertmanager.
// It rollbacks the save if we fail to apply the configuration.
func (am *Alertmanager) SaveAndApplyConfig(cfg *apimodels.PostableUserConfig) error {
@@ -122,6 +122,30 @@ func TestNotificationChannels(t *testing.T) {
mockChannel.matchesExpNotifications(t, expNonEmailNotifications)
require.Equal(t, expEmailNotifications, mockEmail.emails)
require.NoError(t, mockChannel.Close())
{
// Delete the configuration; so it returns the default configuration.
u := fmt.Sprintf("http://grafana:password@%s/api/alertmanager/grafana/config/api/v1/alerts", grafanaListedAddr)
req, err := http.NewRequest(http.MethodDelete, u, nil)
require.NoError(t, err)
client := &http.Client{}
resp, err := client.Do(req)
require.NoError(t, err)
t.Cleanup(func() {
err := resp.Body.Close()
require.NoError(t, err)
})
b, err := ioutil.ReadAll(resp.Body)
require.NoError(t, err)
require.Equal(t, 202, resp.StatusCode)
require.JSONEq(t, `{"message":"configuration deleted; the default is applied"}`, string(b))
alertsURL := fmt.Sprintf("http://grafana:password@%s/api/alertmanager/grafana/config/api/v1/alerts", grafanaListedAddr)
resp = getRequest(t, alertsURL, http.StatusOK) // nolint
b, err = ioutil.ReadAll(resp.Body)
require.NoError(t, err)
require.JSONEq(t, defaultAlertmanagerConfigJSON, string(b))
}
}
func getAlertmanagerConfig(channelAddr string) string {