Skip to content

Commit

Permalink
API: Do not validate/save legacy alerts when saving a dashboard if le…
Browse files Browse the repository at this point in the history
…gacy alerting is disabled (grafana#51883)

* API: Do not validate/save legacy alerts if legacy alerting is disabled

Co-authored-by: Ida Furjesova <[email protected]>
  • Loading branch information
papagian and idafurjes authored Jul 13, 2022
1 parent c4c7908 commit b3992df
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 26 deletions.
55 changes: 32 additions & 23 deletions pkg/services/dashboards/service/dashboard_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ func (dr *DashboardServiceImpl) SaveProvisionedDashboard(ctx context.Context, dt
},
}

cmd, err := dr.BuildSaveDashboardCommand(ctx, dto, true, false)
cmd, err := dr.BuildSaveDashboardCommand(ctx, dto, setting.IsLegacyAlertingEnabled(), false)
if err != nil {
return nil, err
}
Expand All @@ -243,14 +243,17 @@ func (dr *DashboardServiceImpl) SaveProvisionedDashboard(ctx context.Context, dt
OrgID: dto.OrgId,
}

alerts, err := dr.dashAlertExtractor.GetAlerts(ctx, dashAlertInfo)
if err != nil {
return nil, err
}
// extract/save legacy alerts only if legacy alerting is enabled
if setting.IsLegacyAlertingEnabled() {
alerts, err := dr.dashAlertExtractor.GetAlerts(ctx, dashAlertInfo)
if err != nil {
return nil, err
}

err = dr.dashboardStore.SaveAlerts(ctx, dash.Id, alerts)
if err != nil {
return nil, err
err = dr.dashboardStore.SaveAlerts(ctx, dash.Id, alerts)
if err != nil {
return nil, err
}
}

if dto.Dashboard.Id == 0 {
Expand Down Expand Up @@ -284,14 +287,17 @@ func (dr *DashboardServiceImpl) SaveFolderForProvisionedDashboards(ctx context.C
OrgID: dto.OrgId,
}

alerts, err := dr.dashAlertExtractor.GetAlerts(ctx, dashAlertInfo)
if err != nil {
return nil, err
}
// extract/save legacy alerts only if legacy alerting is enabled
if setting.IsLegacyAlertingEnabled() {
alerts, err := dr.dashAlertExtractor.GetAlerts(ctx, dashAlertInfo)
if err != nil {
return nil, err
}

err = dr.dashboardStore.SaveAlerts(ctx, dash.Id, alerts)
if err != nil {
return nil, err
err = dr.dashboardStore.SaveAlerts(ctx, dash.Id, alerts)
if err != nil {
return nil, err
}
}

if dto.Dashboard.Id == 0 {
Expand All @@ -312,7 +318,7 @@ func (dr *DashboardServiceImpl) SaveDashboard(ctx context.Context, dto *dashboar
dto.Dashboard.Data.Set("refresh", setting.MinRefreshInterval)
}

cmd, err := dr.BuildSaveDashboardCommand(ctx, dto, true, !allowUiUpdate)
cmd, err := dr.BuildSaveDashboardCommand(ctx, dto, setting.IsLegacyAlertingEnabled(), !allowUiUpdate)
if err != nil {
return nil, err
}
Expand All @@ -328,14 +334,17 @@ func (dr *DashboardServiceImpl) SaveDashboard(ctx context.Context, dto *dashboar
OrgID: dto.OrgId,
}

alerts, err := dr.dashAlertExtractor.GetAlerts(ctx, dashAlertInfo)
if err != nil {
return nil, err
}
// extract/save legacy alerts only if legacy alerting is enabled
if setting.IsLegacyAlertingEnabled() {
alerts, err := dr.dashAlertExtractor.GetAlerts(ctx, dashAlertInfo)
if err != nil {
return nil, err
}

err = dr.dashboardStore.SaveAlerts(ctx, dash.Id, alerts)
if err != nil {
return nil, err
err = dr.dashboardStore.SaveAlerts(ctx, dash.Id, alerts)
if err != nil {
return nil, err
}
}

// new dashboard created
Expand Down
21 changes: 18 additions & 3 deletions pkg/services/dashboards/service/dashboard_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"github.com/xorcare/pointer"

"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/infra/log"
Expand All @@ -23,7 +24,9 @@ func TestIntegrationDashboardService(t *testing.T) {
t.Run("Dashboard service tests", func(t *testing.T) {
fakeStore := dashboards.FakeDashboardStore{}
defer fakeStore.AssertExpectations(t)

service := &DashboardServiceImpl{
cfg: setting.NewCfg(),
log: log.New("test.logger"),
dashboardStore: &fakeStore,
dashAlertExtractor: &dummyDashAlertExtractor{},
Expand Down Expand Up @@ -100,7 +103,6 @@ func TestIntegrationDashboardService(t *testing.T) {
t.Run("Should not return validation error if dashboard is provisioned but UI updates allowed", func(t *testing.T) {
fakeStore.On("ValidateDashboardBeforeSave", mock.Anything, mock.Anything).Return(true, nil).Once()
fakeStore.On("SaveDashboard", mock.Anything).Return(&models.Dashboard{Data: simplejson.New()}, nil).Once()
fakeStore.On("SaveAlerts", mock.Anything, mock.Anything, mock.Anything).Return(nil).Once()

dto.Dashboard = models.NewDashboard("Dash")
dto.Dashboard.SetId(3)
Expand All @@ -110,6 +112,20 @@ func TestIntegrationDashboardService(t *testing.T) {
})

t.Run("Should return validation error if alert data is invalid", func(t *testing.T) {
origAlertingEnabledSet := setting.AlertingEnabled != nil
origAlertingEnabledVal := false
if origAlertingEnabledSet {
origAlertingEnabledVal = *setting.AlertingEnabled
}
setting.AlertingEnabled = pointer.Bool(true)
t.Cleanup(func() {
if !origAlertingEnabledSet {
setting.AlertingEnabled = nil
} else {
setting.AlertingEnabled = &origAlertingEnabledVal
}
})

fakeStore.On("ValidateDashboardBeforeSave", mock.Anything, mock.Anything).Return(true, nil).Once()
fakeStore.On("GetProvisionedDataByDashboardID", mock.Anything).Return(nil, nil).Once()
fakeStore.On("SaveDashboard", mock.Anything).Return(&models.Dashboard{Data: simplejson.New()}, nil).Once()
Expand All @@ -118,6 +134,7 @@ func TestIntegrationDashboardService(t *testing.T) {
dto.Dashboard = models.NewDashboard("Dash")
dto.User = &models.SignedInUser{UserId: 1}
_, err := service.SaveDashboard(context.Background(), dto, false)
require.Error(t, err)
require.Equal(t, err.Error(), "alert validation error")
})
})
Expand All @@ -128,7 +145,6 @@ func TestIntegrationDashboardService(t *testing.T) {
t.Run("Should not return validation error if dashboard is provisioned", func(t *testing.T) {
fakeStore.On("ValidateDashboardBeforeSave", mock.Anything, mock.Anything).Return(true, nil).Once()
fakeStore.On("SaveProvisionedDashboard", mock.Anything, mock.Anything).Return(&models.Dashboard{Data: simplejson.New()}, nil).Once()
fakeStore.On("SaveAlerts", mock.Anything, mock.Anything, mock.Anything).Return(nil).Once()

dto.Dashboard = models.NewDashboard("Dash")
dto.Dashboard.SetId(3)
Expand All @@ -140,7 +156,6 @@ func TestIntegrationDashboardService(t *testing.T) {
t.Run("Should override invalid refresh interval if dashboard is provisioned", func(t *testing.T) {
fakeStore.On("ValidateDashboardBeforeSave", mock.Anything, mock.Anything).Return(true, nil).Once()
fakeStore.On("SaveProvisionedDashboard", mock.Anything, mock.Anything).Return(&models.Dashboard{Data: simplejson.New()}, nil).Once()
fakeStore.On("SaveAlerts", mock.Anything, mock.Anything, mock.Anything).Return(nil).Once()

oldRefreshInterval := setting.MinRefreshInterval
setting.MinRefreshInterval = "5m"
Expand Down
6 changes: 6 additions & 0 deletions pkg/setting/setting.go
Original file line number Diff line number Diff line change
Expand Up @@ -1445,6 +1445,12 @@ func readAlertingSettings(iniFile *ini.File) error {
return nil
}

// IsLegacyAlertingEnabled returns whether the legacy alerting is enabled or not.
// It's safe to be used only after readAlertingSettings() and ReadUnifiedAlertingSettings() are executed.
func IsLegacyAlertingEnabled() bool {
return AlertingEnabled != nil && *AlertingEnabled
}

func readSnapshotsSettings(cfg *Cfg, iniFile *ini.File) error {
snapshots := iniFile.Section("snapshots")

Expand Down

0 comments on commit b3992df

Please sign in to comment.