Add context.Context to AlertingStore (#45069)

pull/45134/head
George Robinson 3 years ago committed by GitHub
parent 069f772c6f
commit 4e3a72fc2a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      pkg/services/ngalert/api/api.go
  2. 16
      pkg/services/ngalert/api/api_alertmanager.go
  3. 13
      pkg/services/ngalert/api/api_alertmanager_test.go
  4. 3
      pkg/services/ngalert/api/testing.go
  5. 8
      pkg/services/ngalert/notifier/alertmanager.go
  6. 2
      pkg/services/ngalert/notifier/multiorg_alertmanager.go
  7. 6
      pkg/services/ngalert/notifier/testing.go
  8. 12
      pkg/services/ngalert/store/alertmanager.go
  9. 6
      pkg/services/ngalert/store/database.go

@ -32,8 +32,8 @@ type Scheduler interface {
type Alertmanager interface {
// Configuration
SaveAndApplyConfig(config *apimodels.PostableUserConfig) error
SaveAndApplyDefaultConfig() error
SaveAndApplyConfig(ctx context.Context, config *apimodels.PostableUserConfig) error
SaveAndApplyDefaultConfig(ctx context.Context) error
GetStatus() apimodels.GettableStatus
// Silences
@ -51,7 +51,7 @@ type Alertmanager interface {
}
type AlertingStore interface {
GetLatestAlertmanagerConfiguration(query *models.GetLatestAlertmanagerConfigurationQuery) error
GetLatestAlertmanagerConfiguration(ctx context.Context, query *models.GetLatestAlertmanagerConfigurationQuery) error
}
// API handlers.

@ -42,10 +42,10 @@ func (e UnknownReceiverError) Error() string {
return fmt.Sprintf("unknown receiver: %s", e.UID)
}
func (srv AlertmanagerSrv) loadSecureSettings(orgId int64, receivers []*apimodels.PostableApiReceiver) error {
func (srv AlertmanagerSrv) loadSecureSettings(ctx context.Context, 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 err := srv.store.GetLatestAlertmanagerConfiguration(ctx, &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)
@ -159,7 +159,7 @@ func (srv AlertmanagerSrv) RouteDeleteAlertingConfig(c *models.ReqContext) respo
return errResp
}
if err := am.SaveAndApplyDefaultConfig(); err != nil {
if err := am.SaveAndApplyDefaultConfig(c.Req.Context()); 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")
}
@ -193,7 +193,7 @@ func (srv AlertmanagerSrv) RouteGetAlertingConfig(c *models.ReqContext) response
}
query := ngmodels.GetLatestAlertmanagerConfigurationQuery{OrgID: c.OrgId}
if err := srv.store.GetLatestAlertmanagerConfiguration(&query); err != nil {
if err := srv.store.GetLatestAlertmanagerConfiguration(c.Req.Context(), &query); err != nil {
if errors.Is(err, store.ErrNoAlertmanagerConfiguration) {
return ErrResp(http.StatusNotFound, err, "")
}
@ -340,14 +340,14 @@ func (srv AlertmanagerSrv) RoutePostAlertingConfig(c *models.ReqContext, body ap
// Get the last known working configuration
query := ngmodels.GetLatestAlertmanagerConfigurationQuery{OrgID: c.OrgId}
if err := srv.store.GetLatestAlertmanagerConfiguration(&query); err != nil {
if err := srv.store.GetLatestAlertmanagerConfiguration(c.Req.Context(), &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 ErrResp(http.StatusInternalServerError, err, "failed to get latest configuration")
}
}
if err := srv.loadSecureSettings(c.OrgId, body.AlertmanagerConfig.Receivers); err != nil {
if err := srv.loadSecureSettings(c.Req.Context(), c.OrgId, body.AlertmanagerConfig.Receivers); err != nil {
var unknownReceiverError UnknownReceiverError
if errors.As(err, &unknownReceiverError) {
return ErrResp(http.StatusBadRequest, err, "")
@ -367,7 +367,7 @@ func (srv AlertmanagerSrv) RoutePostAlertingConfig(c *models.ReqContext, body ap
}
}
if err := am.SaveAndApplyConfig(&body); err != nil {
if err := am.SaveAndApplyConfig(c.Req.Context(), &body); err != nil {
srv.log.Error("unable to save and apply alertmanager configuration", "err", err)
return ErrResp(http.StatusBadRequest, err, "failed to save and apply Alertmanager configuration")
}
@ -384,7 +384,7 @@ func (srv AlertmanagerSrv) RoutePostTestReceivers(c *models.ReqContext, body api
return accessForbiddenResp()
}
if err := srv.loadSecureSettings(c.OrgId, body.Receivers); err != nil {
if err := srv.loadSecureSettings(c.Req.Context(), c.OrgId, body.Receivers); err != nil {
var unknownReceiverError UnknownReceiverError
if errors.As(err, &unknownReceiverError) {
return ErrResp(http.StatusBadRequest, err, "")

@ -17,6 +17,7 @@ import (
"github.com/grafana/grafana/pkg/services/secrets/fakes"
secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/web"
"github.com/prometheus/client_golang/prometheus"
"github.com/stretchr/testify/require"
)
@ -155,6 +156,9 @@ func TestAlertmanagerConfig(t *testing.T) {
t.Run("assert 404 Not Found when applying config to nonexistent org", func(t *testing.T) {
rc := models.ReqContext{
Context: &web.Context{
Req: &http.Request{},
},
SignedInUser: &models.SignedInUser{
OrgRole: models.ROLE_EDITOR,
OrgId: 12,
@ -170,6 +174,9 @@ func TestAlertmanagerConfig(t *testing.T) {
t.Run("assert 403 Forbidden when applying config while not Editor", func(t *testing.T) {
rc := models.ReqContext{
Context: &web.Context{
Req: &http.Request{},
},
SignedInUser: &models.SignedInUser{
OrgRole: models.ROLE_VIEWER,
OrgId: 1,
@ -185,6 +192,9 @@ func TestAlertmanagerConfig(t *testing.T) {
t.Run("assert 202 when config successfully applied", func(t *testing.T) {
rc := models.ReqContext{
Context: &web.Context{
Req: &http.Request{},
},
SignedInUser: &models.SignedInUser{
OrgRole: models.ROLE_EDITOR,
OrgId: 1,
@ -200,6 +210,9 @@ func TestAlertmanagerConfig(t *testing.T) {
t.Run("assert 202 when alertmanager to configure is not ready", func(t *testing.T) {
sut := createSut(t)
rc := models.ReqContext{
Context: &web.Context{
Req: &http.Request{},
},
SignedInUser: &models.SignedInUser{
OrgRole: models.ROLE_EDITOR,
OrgId: 3, // Org 3 was initialized with broken config.

@ -1,6 +1,7 @@
package api
import (
"context"
"testing"
"github.com/grafana/grafana/pkg/services/ngalert/models"
@ -23,7 +24,7 @@ func (f FakeAlertingStore) Setup(orgID int64) {
f.orgsWithConfig[orgID] = true
}
func (f FakeAlertingStore) GetLatestAlertmanagerConfiguration(query *models.GetLatestAlertmanagerConfigurationQuery) error {
func (f FakeAlertingStore) GetLatestAlertmanagerConfiguration(_ context.Context, query *models.GetLatestAlertmanagerConfigurationQuery) error {
if _, ok := f.orgsWithConfig[query.OrgID]; ok {
return nil
}

@ -232,7 +232,7 @@ func (am *Alertmanager) StopAndWait() {
// 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 {
func (am *Alertmanager) SaveAndApplyDefaultConfig(ctx context.Context) error {
am.reloadConfigMtx.Lock()
defer am.reloadConfigMtx.Unlock()
@ -248,7 +248,7 @@ func (am *Alertmanager) SaveAndApplyDefaultConfig() error {
return err
}
err = am.Store.SaveAlertmanagerConfigurationWithCallback(cmd, func() error {
err = am.Store.SaveAlertmanagerConfigurationWithCallback(ctx, cmd, func() error {
if err := am.applyConfig(cfg, []byte(am.Settings.UnifiedAlerting.DefaultConfiguration)); err != nil {
return err
}
@ -263,7 +263,7 @@ func (am *Alertmanager) SaveAndApplyDefaultConfig() error {
// 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 {
func (am *Alertmanager) SaveAndApplyConfig(ctx context.Context, cfg *apimodels.PostableUserConfig) error {
rawConfig, err := json.Marshal(&cfg)
if err != nil {
return fmt.Errorf("failed to serialize to the Alertmanager configuration: %w", err)
@ -278,7 +278,7 @@ func (am *Alertmanager) SaveAndApplyConfig(cfg *apimodels.PostableUserConfig) er
OrgID: am.orgID,
}
err = am.Store.SaveAlertmanagerConfigurationWithCallback(cmd, func() error {
err = am.Store.SaveAlertmanagerConfigurationWithCallback(ctx, cmd, func() error {
if err := am.applyConfig(cfg, rawConfig); err != nil {
return err
}

@ -188,7 +188,7 @@ func (moa *MultiOrgAlertmanager) SyncAlertmanagersForOrgs(ctx context.Context, o
// This means that the configuration is gone but the organization, as well as the Alertmanager, exists.
moa.logger.Warn("Alertmanager exists for org but the configuration is gone. Applying the default configuration", "org", orgID)
}
err := alertmanager.SaveAndApplyDefaultConfig()
err := alertmanager.SaveAndApplyDefaultConfig(ctx)
if err != nil {
moa.logger.Error("failed to apply the default Alertmanager configuration", "org", orgID)
continue

@ -31,7 +31,7 @@ func (f *FakeConfigStore) GetAllLatestAlertmanagerConfiguration(context.Context)
return result, nil
}
func (f *FakeConfigStore) GetLatestAlertmanagerConfiguration(query *models.GetLatestAlertmanagerConfigurationQuery) error {
func (f *FakeConfigStore) GetLatestAlertmanagerConfiguration(_ context.Context, query *models.GetLatestAlertmanagerConfigurationQuery) error {
var ok bool
query.Result, ok = f.configs[query.OrgID]
if !ok {
@ -41,7 +41,7 @@ func (f *FakeConfigStore) GetLatestAlertmanagerConfiguration(query *models.GetLa
return nil
}
func (f *FakeConfigStore) SaveAlertmanagerConfiguration(cmd *models.SaveAlertmanagerConfigurationCmd) error {
func (f *FakeConfigStore) SaveAlertmanagerConfiguration(_ context.Context, cmd *models.SaveAlertmanagerConfigurationCmd) error {
f.configs[cmd.OrgID] = &models.AlertConfiguration{
AlertmanagerConfiguration: cmd.AlertmanagerConfiguration,
OrgID: cmd.OrgID,
@ -52,7 +52,7 @@ func (f *FakeConfigStore) SaveAlertmanagerConfiguration(cmd *models.SaveAlertman
return nil
}
func (f *FakeConfigStore) SaveAlertmanagerConfigurationWithCallback(cmd *models.SaveAlertmanagerConfigurationCmd, callback store.SaveCallback) error {
func (f *FakeConfigStore) SaveAlertmanagerConfigurationWithCallback(_ context.Context, cmd *models.SaveAlertmanagerConfigurationCmd, callback store.SaveCallback) error {
f.configs[cmd.OrgID] = &models.AlertConfiguration{
AlertmanagerConfiguration: cmd.AlertmanagerConfiguration,
OrgID: cmd.OrgID,

@ -17,8 +17,8 @@ var (
// GetLatestAlertmanagerConfiguration returns the lastest version of the alertmanager configuration.
// It returns ErrNoAlertmanagerConfiguration if no configuration is found.
func (st *DBstore) GetLatestAlertmanagerConfiguration(query *models.GetLatestAlertmanagerConfigurationQuery) error {
return st.SQLStore.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error {
func (st *DBstore) GetLatestAlertmanagerConfiguration(ctx context.Context, query *models.GetLatestAlertmanagerConfigurationQuery) error {
return st.SQLStore.WithDbSession(ctx, func(sess *sqlstore.DBSession) error {
c := &models.AlertConfiguration{}
// The ID is already an auto incremental column, using the ID as an order should guarantee the latest.
ok, err := sess.Desc("id").Where("org_id = ?", query.OrgID).Limit(1).Get(c)
@ -52,16 +52,16 @@ func (st *DBstore) GetAllLatestAlertmanagerConfiguration(ctx context.Context) ([
}
// SaveAlertmanagerConfiguration creates an alertmanager configuration.
func (st DBstore) SaveAlertmanagerConfiguration(cmd *models.SaveAlertmanagerConfigurationCmd) error {
return st.SaveAlertmanagerConfigurationWithCallback(cmd, func() error { return nil })
func (st DBstore) SaveAlertmanagerConfiguration(ctx context.Context, cmd *models.SaveAlertmanagerConfigurationCmd) error {
return st.SaveAlertmanagerConfigurationWithCallback(ctx, cmd, func() error { return nil })
}
type SaveCallback func() error
// SaveAlertmanagerConfigurationWithCallback creates an alertmanager configuration version and then executes a callback.
// If the callback results in error it rolls back the transaction.
func (st DBstore) SaveAlertmanagerConfigurationWithCallback(cmd *models.SaveAlertmanagerConfigurationCmd, callback SaveCallback) error {
return st.SQLStore.WithTransactionalDbSession(context.Background(), func(sess *sqlstore.DBSession) error {
func (st DBstore) SaveAlertmanagerConfigurationWithCallback(ctx context.Context, cmd *models.SaveAlertmanagerConfigurationCmd, callback SaveCallback) error {
return st.SQLStore.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error {
config := models.AlertConfiguration{
AlertmanagerConfiguration: cmd.AlertmanagerConfiguration,
ConfigurationVersion: cmd.ConfigurationVersion,

@ -17,10 +17,10 @@ const AlertDefinitionMaxTitleLength = 190
// AlertingStore is the database interface used by the Alertmanager service.
type AlertingStore interface {
GetLatestAlertmanagerConfiguration(*models.GetLatestAlertmanagerConfigurationQuery) error
GetLatestAlertmanagerConfiguration(ctx context.Context, query *models.GetLatestAlertmanagerConfigurationQuery) error
GetAllLatestAlertmanagerConfiguration(ctx context.Context) ([]*models.AlertConfiguration, error)
SaveAlertmanagerConfiguration(*models.SaveAlertmanagerConfigurationCmd) error
SaveAlertmanagerConfigurationWithCallback(*models.SaveAlertmanagerConfigurationCmd, SaveCallback) error
SaveAlertmanagerConfiguration(ctx context.Context, cmd *models.SaveAlertmanagerConfigurationCmd) error
SaveAlertmanagerConfigurationWithCallback(ctx context.Context, cmd *models.SaveAlertmanagerConfigurationCmd, callback SaveCallback) error
}
// DBstore stores the alert definitions and instances in the database.

Loading…
Cancel
Save