mirror of
https://github.com/grafana/grafana.git
synced 2025-07-31 07:42:31 +08:00
Alerting: API to delete extra Alertmanager configurations (#106892)
This commit is contained in:

committed by
GitHub

parent
02bdac447d
commit
def5d889d0
@ -127,6 +127,7 @@ type ConvertPrometheusSrv struct {
|
||||
}
|
||||
|
||||
type Alertmanager interface {
|
||||
DeleteExtraConfiguration(ctx context.Context, org int64, identifier string) error
|
||||
GetAlertmanagerConfiguration(ctx context.Context, org int64, withAutogen bool) (apimodels.GettableUserConfig, error)
|
||||
}
|
||||
|
||||
@ -579,7 +580,26 @@ func (srv *ConvertPrometheusSrv) RouteConvertPrometheusGetAlertmanagerConfig(c *
|
||||
}
|
||||
|
||||
func (srv *ConvertPrometheusSrv) RouteConvertPrometheusDeleteAlertmanagerConfig(c *contextmodel.ReqContext) response.Response {
|
||||
return response.Error(http.StatusNotImplemented, "Not Implemented", nil)
|
||||
if !srv.featureToggles.IsEnabledGlobally(featuremgmt.FlagAlertingImportAlertmanagerAPI) {
|
||||
return response.Error(http.StatusNotImplemented, "Not Implemented", nil)
|
||||
}
|
||||
|
||||
logger := srv.logger.FromContext(c.Req.Context())
|
||||
|
||||
identifier, err := parseConfigIdentifierHeader(c)
|
||||
if err != nil {
|
||||
logger.Error("Failed to parse config identifier header", "error", err)
|
||||
return errorToResponse(err)
|
||||
}
|
||||
|
||||
err = srv.am.DeleteExtraConfiguration(c.Req.Context(), c.GetOrgID(), identifier)
|
||||
if err != nil {
|
||||
logger.Error("Failed to delete alertmanager configuration", "error", err, "identifier", identifier)
|
||||
return errorToResponse(fmt.Errorf("failed to delete alertmanager configuration: %w", err))
|
||||
}
|
||||
|
||||
logger.Info("Successfully deleted extra alertmanager configuration", "identifier", identifier)
|
||||
return successfulResponse()
|
||||
}
|
||||
|
||||
// parseBooleanHeader parses a boolean header value, returning an error if the header
|
||||
|
@ -1510,7 +1510,7 @@ func (m *mockAlertmanager) GetAlertmanagerConfiguration(ctx context.Context, org
|
||||
return args.Get(0).(apimodels.GettableUserConfig), args.Error(1)
|
||||
}
|
||||
|
||||
func (m *mockAlertmanager) DeleteAndApplyExtraConfiguration(ctx context.Context, org int64, identifier string) error {
|
||||
func (m *mockAlertmanager) DeleteExtraConfiguration(ctx context.Context, org int64, identifier string) error {
|
||||
args := m.Called(ctx, org, identifier)
|
||||
return args.Error(0)
|
||||
}
|
||||
@ -1799,3 +1799,67 @@ func TestFormatMergeMatchers(t *testing.T) {
|
||||
require.Equal(t, "env=prod,team=backend", result)
|
||||
})
|
||||
}
|
||||
|
||||
func TestRouteConvertPrometheusDeleteAlertmanagerConfig(t *testing.T) {
|
||||
const identifier = "test-config"
|
||||
const orgID = int64(1)
|
||||
|
||||
mockAM := &mockAlertmanager{}
|
||||
ft := featuremgmt.WithFeatures(featuremgmt.FlagAlertingImportAlertmanagerAPI)
|
||||
srv, _, _ := createConvertPrometheusSrv(t, withAlertmanager(mockAM), withFeatureToggles(ft))
|
||||
|
||||
t.Run("should parse identifier header and call DeleteExtraConfiguration", func(t *testing.T) {
|
||||
mockAM.On("DeleteExtraConfiguration", mock.Anything, orgID, identifier).Return(nil).Once()
|
||||
|
||||
rc := createRequestCtx()
|
||||
rc.Req.Header.Set(configIdentifierHeader, identifier)
|
||||
|
||||
response := srv.RouteConvertPrometheusDeleteAlertmanagerConfig(rc)
|
||||
|
||||
require.Equal(t, http.StatusAccepted, response.Status())
|
||||
mockAM.AssertExpectations(t)
|
||||
})
|
||||
|
||||
t.Run("should return error when identifier header is missing", func(t *testing.T) {
|
||||
rc := createRequestCtx()
|
||||
|
||||
response := srv.RouteConvertPrometheusDeleteAlertmanagerConfig(rc)
|
||||
|
||||
require.Equal(t, http.StatusBadRequest, response.Status())
|
||||
require.Contains(t, string(response.Body()), "identifier cannot be empty")
|
||||
})
|
||||
|
||||
t.Run("should return error when DeleteExtraConfiguration fails", func(t *testing.T) {
|
||||
mockAM.On("DeleteExtraConfiguration", mock.Anything, orgID, identifier).Return(errors.New("delete error")).Once()
|
||||
|
||||
rc := createRequestCtx()
|
||||
rc.Req.Header.Set(configIdentifierHeader, identifier)
|
||||
|
||||
response := srv.RouteConvertPrometheusDeleteAlertmanagerConfig(rc)
|
||||
|
||||
require.Equal(t, http.StatusInternalServerError, response.Status())
|
||||
mockAM.AssertExpectations(t)
|
||||
})
|
||||
|
||||
t.Run("should return not implemented when feature toggle is disabled", func(t *testing.T) {
|
||||
ft := featuremgmt.WithFeatures()
|
||||
srv, _, _ := createConvertPrometheusSrv(t, withAlertmanager(mockAM), withFeatureToggles(ft))
|
||||
|
||||
rc := createRequestCtx()
|
||||
rc.Req.Header.Set(configIdentifierHeader, identifier)
|
||||
|
||||
response := srv.RouteConvertPrometheusDeleteAlertmanagerConfig(rc)
|
||||
|
||||
require.Equal(t, http.StatusNotImplemented, response.Status())
|
||||
})
|
||||
|
||||
t.Run("should return error for empty identifier header", func(t *testing.T) {
|
||||
rc := createRequestCtx()
|
||||
rc.Req.Header.Set(configIdentifierHeader, "")
|
||||
|
||||
response := srv.RouteConvertPrometheusDeleteAlertmanagerConfig(rc)
|
||||
|
||||
require.Equal(t, http.StatusBadRequest, response.Status())
|
||||
require.Contains(t, string(response.Body()), "identifier cannot be empty")
|
||||
})
|
||||
}
|
||||
|
@ -412,8 +412,8 @@ func (moa *MultiOrgAlertmanager) SaveAndApplyExtraConfiguration(ctx context.Cont
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteAndApplyExtraConfiguration deletes an ExtraConfiguration by its identifier while preserving the main AlertmanagerConfig.
|
||||
func (moa *MultiOrgAlertmanager) DeleteAndApplyExtraConfiguration(ctx context.Context, org int64, identifier string) error {
|
||||
// DeleteExtraConfiguration deletes an ExtraConfiguration by its identifier while preserving the main AlertmanagerConfig.
|
||||
func (moa *MultiOrgAlertmanager) DeleteExtraConfiguration(ctx context.Context, org int64, identifier string) error {
|
||||
modifyFunc := func(configs []definitions.ExtraConfiguration) ([]definitions.ExtraConfiguration, error) {
|
||||
filtered := make([]definitions.ExtraConfiguration, 0, len(configs))
|
||||
for _, ec := range configs {
|
||||
|
@ -150,7 +150,7 @@ receivers:
|
||||
})
|
||||
}
|
||||
|
||||
func TestMultiOrgAlertmanager_DeleteAndApplyExtraConfiguration(t *testing.T) {
|
||||
func TestMultiOrgAlertmanager_DeleteExtraConfiguration(t *testing.T) {
|
||||
orgID := int64(1)
|
||||
|
||||
t.Run("successfully delete existing extra configuration", func(t *testing.T) {
|
||||
@ -176,7 +176,7 @@ receivers:
|
||||
require.NoError(t, err)
|
||||
require.Len(t, gettableConfig.ExtraConfigs, 1)
|
||||
|
||||
err = mam.DeleteAndApplyExtraConfiguration(ctx, orgID, identifier)
|
||||
err = mam.DeleteExtraConfiguration(ctx, orgID, identifier)
|
||||
require.NoError(t, err)
|
||||
|
||||
gettableConfig, err = mam.GetAlertmanagerConfiguration(ctx, orgID, false)
|
||||
@ -189,7 +189,7 @@ receivers:
|
||||
ctx := context.Background()
|
||||
require.NoError(t, mam.LoadAndSyncAlertmanagersForOrgs(ctx))
|
||||
|
||||
err := mam.DeleteAndApplyExtraConfiguration(ctx, orgID, "non-existent")
|
||||
err := mam.DeleteExtraConfiguration(ctx, orgID, "non-existent")
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
@ -197,7 +197,7 @@ receivers:
|
||||
mam := setupMam(t, nil)
|
||||
ctx := context.Background()
|
||||
|
||||
err := mam.DeleteAndApplyExtraConfiguration(ctx, 999, "test-config")
|
||||
err := mam.DeleteExtraConfiguration(ctx, 999, "test-config")
|
||||
require.Error(t, err)
|
||||
require.ErrorContains(t, err, "failed to get current configuration")
|
||||
})
|
||||
|
Reference in New Issue
Block a user