grafana/pkg/services/ngalert/provisioning/config_test.go
Yuri Tseretyan 494f36e0bd
Alerting: Update provisioning services that handle Alertmanager configuraiton to access config via storage (#79814)
* extract get and save operations to a alertmanagerConfigStore. this removes duplicated code in service (currently only mute timings) and improves testing
* replace generic errors with errutils one with better messages.
* update provisioning services to use new store

---------

Co-authored-by: Alexander Weaver <weaver.alex.d@gmail.com>
2024-01-05 16:15:18 -05:00

128 lines
4.5 KiB
Go

package provisioning
import (
"context"
"encoding/json"
"errors"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
"github.com/grafana/grafana/pkg/services/ngalert/models"
)
func TestAlertmanagerConfigStoreGet(t *testing.T) {
orgID := int64(1)
t.Run("should read the latest config for giving organization", func(t *testing.T) {
storeMock := &MockAMConfigStore{}
store := &alertmanagerConfigStoreImpl{store: storeMock}
expected := models.AlertConfiguration{
ID: 1,
AlertmanagerConfiguration: defaultConfig,
ConfigurationHash: "config-hash-123",
ConfigurationVersion: "123",
CreatedAt: time.Now().Unix(),
Default: false,
OrgID: orgID,
}
expectedCfg := definitions.PostableUserConfig{}
require.NoError(t, json.Unmarshal([]byte(defaultConfig), &expectedCfg))
storeMock.EXPECT().GetLatestAlertmanagerConfiguration(mock.Anything, mock.Anything).Return(&expected, nil)
revision, err := store.Get(context.Background(), orgID)
require.NoError(t, err)
require.Equal(t, expected.ConfigurationVersion, revision.version)
require.Equal(t, expected.ConfigurationHash, revision.concurrencyToken)
require.Equal(t, expectedCfg, *revision.cfg)
storeMock.AssertCalled(t, "GetLatestAlertmanagerConfiguration", mock.Anything, orgID)
})
t.Run("propagate errors", func(t *testing.T) {
t.Run("when underlying store fails", func(t *testing.T) {
storeMock := &MockAMConfigStore{}
store := &alertmanagerConfigStoreImpl{store: storeMock}
expectedErr := errors.New("test=err")
storeMock.EXPECT().GetLatestAlertmanagerConfiguration(mock.Anything, mock.Anything).Return(nil, expectedErr)
_, err := store.Get(context.Background(), orgID)
require.ErrorIs(t, err, expectedErr)
})
t.Run("return ErrNoAlertmanagerConfiguration config does not exist", func(t *testing.T) {
storeMock := &MockAMConfigStore{}
store := &alertmanagerConfigStoreImpl{store: storeMock}
storeMock.EXPECT().GetLatestAlertmanagerConfiguration(mock.Anything, mock.Anything).Return(nil, nil)
_, err := store.Get(context.Background(), orgID)
require.Truef(t, ErrNoAlertmanagerConfiguration.Is(err), "expected ErrNoAlertmanagerConfiguration but got %s", err.Error())
})
t.Run("when config cannot be unmarshalled", func(t *testing.T) {
storeMock := &MockAMConfigStore{}
store := &alertmanagerConfigStoreImpl{store: storeMock}
storeMock.EXPECT().GetLatestAlertmanagerConfiguration(mock.Anything, mock.Anything).Return(&models.AlertConfiguration{
AlertmanagerConfiguration: "invalid-json",
}, nil)
_, err := store.Get(context.Background(), orgID)
require.Truef(t, ErrBadAlertmanagerConfiguration.Base.Is(err), "expected ErrBadAlertmanagerConfiguration but got %s", err.Error())
})
})
}
func TestAlertmanagerConfigStoreSave(t *testing.T) {
orgID := int64(1)
cfg := definitions.PostableUserConfig{}
require.NoError(t, json.Unmarshal([]byte(defaultConfig), &cfg))
expectedCfg, err := serializeAlertmanagerConfig(cfg)
require.NoError(t, err)
revision := cfgRevision{
cfg: &cfg,
concurrencyToken: "config-hash-123",
version: "123",
}
t.Run("should save the config to store", func(t *testing.T) {
storeMock := &MockAMConfigStore{}
store := &alertmanagerConfigStoreImpl{store: storeMock}
storeMock.EXPECT().UpdateAlertmanagerConfiguration(mock.Anything, mock.Anything).RunAndReturn(func(ctx context.Context, cmd *models.SaveAlertmanagerConfigurationCmd) error {
assert.Equal(t, string(expectedCfg), cmd.AlertmanagerConfiguration)
assert.Equal(t, orgID, cmd.OrgID)
assert.Equal(t, revision.version, cmd.ConfigurationVersion)
assert.Equal(t, false, cmd.Default)
assert.Equal(t, revision.concurrencyToken, cmd.FetchedConfigurationHash)
return nil
})
err := store.Save(context.Background(), &revision, orgID)
require.NoError(t, err)
storeMock.AssertCalled(t, "UpdateAlertmanagerConfiguration", mock.Anything, mock.Anything)
})
t.Run("propagates errors when underlying storage returns error", func(t *testing.T) {
storeMock := &MockAMConfigStore{}
store := &alertmanagerConfigStoreImpl{store: storeMock}
expectedErr := errors.New("test-err")
storeMock.EXPECT().UpdateAlertmanagerConfiguration(mock.Anything, mock.Anything).Return(expectedErr)
err := store.Save(context.Background(), &revision, orgID)
require.ErrorIs(t, err, expectedErr)
})
}