93 lines
3.0 KiB
Go
93 lines
3.0 KiB
Go
package legacy_storage
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
|
|
"github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
|
"github.com/grafana/grafana/pkg/services/ngalert/models"
|
|
)
|
|
|
|
type amConfigStore interface {
|
|
GetLatestAlertmanagerConfiguration(ctx context.Context, orgID int64) (*models.AlertConfiguration, error)
|
|
UpdateAlertmanagerConfiguration(ctx context.Context, cmd *models.SaveAlertmanagerConfigurationCmd) error
|
|
}
|
|
|
|
func DeserializeAlertmanagerConfig(config []byte) (*definitions.PostableUserConfig, error) {
|
|
result := definitions.PostableUserConfig{}
|
|
if err := json.Unmarshal(config, &result); err != nil {
|
|
return nil, makeErrBadAlertmanagerConfiguration(err)
|
|
}
|
|
return &result, nil
|
|
}
|
|
|
|
func SerializeAlertmanagerConfig(config definitions.PostableUserConfig) ([]byte, error) {
|
|
return json.Marshal(config)
|
|
}
|
|
|
|
type ConfigRevision struct {
|
|
Config *definitions.PostableUserConfig
|
|
ConcurrencyToken string
|
|
Version string
|
|
}
|
|
|
|
func getLastConfiguration(ctx context.Context, orgID int64, store amConfigStore) (*ConfigRevision, error) {
|
|
alertManagerConfig, err := store.GetLatestAlertmanagerConfiguration(ctx, orgID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if alertManagerConfig == nil {
|
|
return nil, ErrNoAlertmanagerConfiguration.Errorf("")
|
|
}
|
|
|
|
concurrencyToken := alertManagerConfig.ConfigurationHash
|
|
cfg, err := DeserializeAlertmanagerConfig([]byte(alertManagerConfig.AlertmanagerConfiguration))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &ConfigRevision{
|
|
Config: cfg,
|
|
ConcurrencyToken: concurrencyToken,
|
|
Version: alertManagerConfig.ConfigurationVersion,
|
|
}, nil
|
|
}
|
|
|
|
type alertmanagerConfigStoreImpl struct {
|
|
store amConfigStore
|
|
}
|
|
|
|
func NewAlertmanagerConfigStore(store amConfigStore) *alertmanagerConfigStoreImpl {
|
|
return &alertmanagerConfigStoreImpl{store: store}
|
|
}
|
|
|
|
func (a alertmanagerConfigStoreImpl) Get(ctx context.Context, orgID int64) (*ConfigRevision, error) {
|
|
return getLastConfiguration(ctx, orgID, a.store)
|
|
}
|
|
|
|
func (a alertmanagerConfigStoreImpl) Save(ctx context.Context, revision *ConfigRevision, orgID int64) error {
|
|
serialized, err := SerializeAlertmanagerConfig(*revision.Config)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
cmd := models.SaveAlertmanagerConfigurationCmd{
|
|
AlertmanagerConfiguration: string(serialized),
|
|
ConfigurationVersion: revision.Version,
|
|
FetchedConfigurationHash: revision.ConcurrencyToken,
|
|
Default: false,
|
|
OrgID: orgID,
|
|
}
|
|
return a.PersistConfig(ctx, &cmd)
|
|
}
|
|
|
|
// PersistConfig validates to config before eventually persisting it if no error occurs
|
|
func (a alertmanagerConfigStoreImpl) PersistConfig(ctx context.Context, cmd *models.SaveAlertmanagerConfigurationCmd) error {
|
|
cfg := &definitions.PostableUserConfig{}
|
|
if err := json.Unmarshal([]byte(cmd.AlertmanagerConfiguration), cfg); err != nil {
|
|
return fmt.Errorf("change would result in an invalid configuration state: %w", err)
|
|
}
|
|
return a.store.UpdateAlertmanagerConfiguration(ctx, cmd)
|
|
}
|