From 03b6ab0d577dfa93af4812a0396ebb8c99125284 Mon Sep 17 00:00:00 2001
From: gotjosh <josue.abreu@gmail.com>
Date: Thu, 14 Jul 2022 18:54:19 +0100
Subject: [PATCH] Unify all the copied files under the `alerting` package

---
 alerting/alertmanager.go                      | 704 ------------------
 alerting/alertmanager_config.go               |   2 +-
 alerting/alerts.go                            |   2 +-
 alerting/available_channels.go                |   2 +-
 alerting/config.go                            |   2 +-
 alerting/config_test.go                       |   2 +-
 alerting/crypto.go                            |   2 +-
 alerting/file_store.go                        |   2 +-
 alerting/file_store_test.go                   |   2 +-
 alerting/grafana_alertmanager.go              |   1 +
 ...r_test.go => grafana_alertmanager_test.go} |   2 +-
 alerting/multiorg_alertmanager.go             |   2 +-
 alerting/multiorg_alertmanager_test.go        |   2 +-
 alerting/receivers.go                         |   2 +-
 alerting/receivers_test.go                    |   2 +-
 alerting/silences.go                          |   2 +-
 alerting/status.go                            |   2 +-
 alerting/testing.go                           |   2 +-
 18 files changed, 17 insertions(+), 720 deletions(-)
 delete mode 100644 alerting/alertmanager.go
 rename alerting/{alertmanager_test.go => grafana_alertmanager_test.go} (99%)

diff --git a/alerting/alertmanager.go b/alerting/alertmanager.go
deleted file mode 100644
index 7243a9ac..00000000
--- a/alerting/alertmanager.go
+++ /dev/null
@@ -1,704 +0,0 @@
-package notifier
-
-import (
-	"context"
-	"crypto/md5"
-	"encoding/base64"
-	"encoding/json"
-	"errors"
-	"fmt"
-	"net/url"
-	"path/filepath"
-	"regexp"
-	"strconv"
-	"sync"
-	"time"
-	"unicode/utf8"
-
-	amv2 "github.com/prometheus/alertmanager/api/v2/models"
-	"github.com/prometheus/alertmanager/cluster"
-	"github.com/prometheus/alertmanager/config"
-	"github.com/prometheus/alertmanager/dispatch"
-	"github.com/prometheus/alertmanager/inhibit"
-	"github.com/prometheus/alertmanager/nflog"
-	"github.com/prometheus/alertmanager/nflog/nflogpb"
-	"github.com/prometheus/alertmanager/notify"
-	"github.com/prometheus/alertmanager/provider/mem"
-	"github.com/prometheus/alertmanager/silence"
-	"github.com/prometheus/alertmanager/template"
-	"github.com/prometheus/alertmanager/timeinterval"
-	"github.com/prometheus/alertmanager/types"
-	"github.com/prometheus/client_golang/prometheus"
-	"github.com/prometheus/common/model"
-
-	pb "github.com/prometheus/alertmanager/silence/silencepb"
-
-	"github.com/grafana/grafana/pkg/infra/kvstore"
-	"github.com/grafana/grafana/pkg/infra/log"
-	apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
-	"github.com/grafana/grafana/pkg/services/ngalert/metrics"
-	ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
-	"github.com/grafana/grafana/pkg/services/ngalert/notifier/channels"
-	"github.com/grafana/grafana/pkg/services/ngalert/store"
-	"github.com/grafana/grafana/pkg/services/notifications"
-	"github.com/grafana/grafana/pkg/setting"
-)
-
-const (
-	notificationLogFilename = "notifications"
-	silencesFilename        = "silences"
-
-	workingDir = "alerting"
-	// maintenanceNotificationAndSilences how often should we flush and gargabe collect notifications and silences
-	maintenanceNotificationAndSilences = 15 * time.Minute
-	// defaultResolveTimeout is the default timeout used for resolving an alert
-	// if the end time is not specified.
-	defaultResolveTimeout = 5 * time.Minute
-	// memoryAlertsGCInterval is the interval at which we'll remove resolved alerts from memory.
-	memoryAlertsGCInterval = 30 * time.Minute
-)
-
-// How long should we keep silences and notification entries on-disk after they've served their purpose.
-var retentionNotificationsAndSilences = 5 * 24 * time.Hour
-var silenceMaintenanceInterval = 15 * time.Minute
-
-func init() {
-	silence.ValidateMatcher = func(m *pb.Matcher) error {
-		switch m.Type {
-		case pb.Matcher_EQUAL, pb.Matcher_NOT_EQUAL:
-			if !model.LabelValue(m.Pattern).IsValid() {
-				return fmt.Errorf("invalid label value %q", m.Pattern)
-			}
-		case pb.Matcher_REGEXP, pb.Matcher_NOT_REGEXP:
-			if _, err := regexp.Compile(m.Pattern); err != nil {
-				return fmt.Errorf("invalid regular expression %q: %s", m.Pattern, err)
-			}
-		default:
-			return fmt.Errorf("unknown matcher type %q", m.Type)
-		}
-		return nil
-	}
-}
-
-type ClusterPeer interface {
-	AddState(string, cluster.State, prometheus.Registerer) cluster.ClusterChannel
-	Position() int
-	WaitReady(context.Context) error
-}
-
-type AlertingStore interface {
-	store.AlertingStore
-	store.ImageStore
-}
-
-type Alertmanager struct {
-	logger log.Logger
-
-	Settings            *setting.Cfg
-	Store               AlertingStore
-	fileStore           *FileStore
-	Metrics             *metrics.Alertmanager
-	NotificationService notifications.Service
-
-	notificationLog *nflog.Log
-	marker          types.Marker
-	alerts          *mem.Alerts
-	route           *dispatch.Route
-	peer            ClusterPeer
-	peerTimeout     time.Duration
-
-	dispatcher *dispatch.Dispatcher
-	inhibitor  *inhibit.Inhibitor
-	// wg is for dispatcher, inhibitor, silences and notifications
-	// Across configuration changes dispatcher and inhibitor are completely replaced, however, silences, notification log and alerts remain the same.
-	// stopc is used to let silences and notifications know we are done.
-	wg    sync.WaitGroup
-	stopc chan struct{}
-
-	silencer *silence.Silencer
-	silences *silence.Silences
-
-	// muteTimes is a map where the key is the name of the mute_time_interval
-	// and the value represents all configured time_interval(s)
-	muteTimes map[string][]timeinterval.TimeInterval
-
-	stageMetrics      *notify.Metrics
-	dispatcherMetrics *dispatch.DispatcherMetrics
-
-	reloadConfigMtx sync.RWMutex
-	config          *apimodels.PostableUserConfig
-	configHash      [16]byte
-	orgID           int64
-
-	decryptFn channels.GetDecryptedValueFn
-}
-
-func newAlertmanager(ctx context.Context, orgID int64, cfg *setting.Cfg, store AlertingStore, kvStore kvstore.KVStore,
-	peer ClusterPeer, decryptFn channels.GetDecryptedValueFn, ns notifications.Service, m *metrics.Alertmanager) (*Alertmanager, error) {
-	am := &Alertmanager{
-		Settings:            cfg,
-		stopc:               make(chan struct{}),
-		logger:              log.New("alertmanager", "org", orgID),
-		marker:              types.NewMarker(m.Registerer),
-		stageMetrics:        notify.NewMetrics(m.Registerer),
-		dispatcherMetrics:   dispatch.NewDispatcherMetrics(false, m.Registerer),
-		Store:               store,
-		peer:                peer,
-		peerTimeout:         cfg.UnifiedAlerting.HAPeerTimeout,
-		Metrics:             m,
-		NotificationService: ns,
-		orgID:               orgID,
-		decryptFn:           decryptFn,
-	}
-
-	am.fileStore = NewFileStore(am.orgID, kvStore, am.WorkingDirPath())
-
-	nflogFilepath, err := am.fileStore.FilepathFor(ctx, notificationLogFilename)
-	if err != nil {
-		return nil, err
-	}
-	silencesFilePath, err := am.fileStore.FilepathFor(ctx, silencesFilename)
-	if err != nil {
-		return nil, err
-	}
-
-	// Initialize the notification log
-	am.wg.Add(1)
-	am.notificationLog, err = nflog.New(
-		nflog.WithRetention(retentionNotificationsAndSilences),
-		nflog.WithSnapshot(nflogFilepath),
-		nflog.WithMaintenance(maintenanceNotificationAndSilences, am.stopc, am.wg.Done, func() (int64, error) {
-			return am.fileStore.Persist(ctx, notificationLogFilename, am.notificationLog)
-		}),
-	)
-	if err != nil {
-		return nil, fmt.Errorf("unable to initialize the notification log component of alerting: %w", err)
-	}
-	c := am.peer.AddState(fmt.Sprintf("notificationlog:%d", am.orgID), am.notificationLog, m.Registerer)
-	am.notificationLog.SetBroadcast(c.Broadcast)
-
-	// Initialize silences
-	am.silences, err = silence.New(silence.Options{
-		Metrics:      m.Registerer,
-		SnapshotFile: silencesFilePath,
-		Retention:    retentionNotificationsAndSilences,
-	})
-	if err != nil {
-		return nil, fmt.Errorf("unable to initialize the silencing component of alerting: %w", err)
-	}
-
-	c = am.peer.AddState(fmt.Sprintf("silences:%d", am.orgID), am.silences, m.Registerer)
-	am.silences.SetBroadcast(c.Broadcast)
-
-	am.wg.Add(1)
-	go func() {
-		am.silences.Maintenance(silenceMaintenanceInterval, silencesFilePath, am.stopc, func() (int64, error) {
-			// Delete silences older than the retention period.
-			if _, err := am.silences.GC(); err != nil {
-				am.logger.Error("silence garbage collection", "err", err)
-				// Don't return here - we need to snapshot our state first.
-			}
-
-			// Snapshot our silences to the Grafana KV store
-			return am.fileStore.Persist(ctx, silencesFilename, am.silences)
-		})
-		am.wg.Done()
-	}()
-
-	// Initialize in-memory alerts
-	am.alerts, err = mem.NewAlerts(context.Background(), am.marker, memoryAlertsGCInterval, nil, am.logger)
-	if err != nil {
-		return nil, fmt.Errorf("unable to initialize the alert provider component of alerting: %w", err)
-	}
-
-	return am, nil
-}
-
-func (am *Alertmanager) Ready() bool {
-	// We consider AM as ready only when the config has been
-	// applied at least once successfully. Until then, some objects
-	// can still be nil.
-	am.reloadConfigMtx.RLock()
-	defer am.reloadConfigMtx.RUnlock()
-
-	return am.ready()
-}
-
-func (am *Alertmanager) ready() bool {
-	return am.config != nil
-}
-
-func (am *Alertmanager) StopAndWait() {
-	if am.dispatcher != nil {
-		am.dispatcher.Stop()
-	}
-
-	if am.inhibitor != nil {
-		am.inhibitor.Stop()
-	}
-
-	am.alerts.Close()
-
-	close(am.stopc)
-
-	am.wg.Wait()
-}
-
-// 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(ctx context.Context) error {
-	am.reloadConfigMtx.Lock()
-	defer am.reloadConfigMtx.Unlock()
-
-	cmd := &ngmodels.SaveAlertmanagerConfigurationCmd{
-		AlertmanagerConfiguration: am.Settings.UnifiedAlerting.DefaultConfiguration,
-		Default:                   true,
-		ConfigurationVersion:      fmt.Sprintf("v%d", ngmodels.AlertConfigurationVersion),
-		OrgID:                     am.orgID,
-	}
-
-	cfg, err := Load([]byte(am.Settings.UnifiedAlerting.DefaultConfiguration))
-	if err != nil {
-		return err
-	}
-
-	err = am.Store.SaveAlertmanagerConfigurationWithCallback(ctx, cmd, func() error {
-		if err := am.applyConfig(cfg, []byte(am.Settings.UnifiedAlerting.DefaultConfiguration)); err != nil {
-			return err
-		}
-		return nil
-	})
-	if err != nil {
-		return err
-	}
-
-	return nil
-}
-
-// 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(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)
-	}
-
-	am.reloadConfigMtx.Lock()
-	defer am.reloadConfigMtx.Unlock()
-
-	cmd := &ngmodels.SaveAlertmanagerConfigurationCmd{
-		AlertmanagerConfiguration: string(rawConfig),
-		ConfigurationVersion:      fmt.Sprintf("v%d", ngmodels.AlertConfigurationVersion),
-		OrgID:                     am.orgID,
-	}
-
-	err = am.Store.SaveAlertmanagerConfigurationWithCallback(ctx, cmd, func() error {
-		if err := am.applyConfig(cfg, rawConfig); err != nil {
-			return err
-		}
-		return nil
-	})
-	if err != nil {
-		return err
-	}
-
-	return nil
-}
-
-// ApplyConfig applies the configuration to the Alertmanager.
-func (am *Alertmanager) ApplyConfig(dbCfg *ngmodels.AlertConfiguration) error {
-	var err error
-	cfg, err := Load([]byte(dbCfg.AlertmanagerConfiguration))
-	if err != nil {
-		return fmt.Errorf("failed to parse Alertmanager config: %w", err)
-	}
-
-	am.reloadConfigMtx.Lock()
-	defer am.reloadConfigMtx.Unlock()
-
-	if err = am.applyConfig(cfg, nil); err != nil {
-		return fmt.Errorf("unable to apply configuration: %w", err)
-	}
-	return nil
-}
-
-func (am *Alertmanager) getTemplate() (*template.Template, error) {
-	am.reloadConfigMtx.RLock()
-	defer am.reloadConfigMtx.RUnlock()
-	if !am.ready() {
-		return nil, errors.New("alertmanager is not initialized")
-	}
-	paths := make([]string, 0, len(am.config.TemplateFiles))
-	for name := range am.config.TemplateFiles {
-		paths = append(paths, filepath.Join(am.WorkingDirPath(), name))
-	}
-	return am.templateFromPaths(paths...)
-}
-
-func (am *Alertmanager) templateFromPaths(paths ...string) (*template.Template, error) {
-	tmpl, err := template.FromGlobs(paths...)
-	if err != nil {
-		return nil, err
-	}
-	externalURL, err := url.Parse(am.Settings.AppURL)
-	if err != nil {
-		return nil, err
-	}
-	tmpl.ExternalURL = externalURL
-	return tmpl, nil
-}
-
-func (am *Alertmanager) buildMuteTimesMap(muteTimeIntervals []config.MuteTimeInterval) map[string][]timeinterval.TimeInterval {
-	muteTimes := make(map[string][]timeinterval.TimeInterval, len(muteTimeIntervals))
-	for _, ti := range muteTimeIntervals {
-		muteTimes[ti.Name] = ti.TimeIntervals
-	}
-	return muteTimes
-}
-
-// applyConfig applies a new configuration by re-initializing all components using the configuration provided.
-// It is not safe to call concurrently.
-func (am *Alertmanager) applyConfig(cfg *apimodels.PostableUserConfig, rawConfig []byte) (err error) {
-	// First, let's make sure this config is not already loaded
-	var configChanged bool
-	if rawConfig == nil {
-		enc, err := json.Marshal(cfg.AlertmanagerConfig)
-		if err != nil {
-			// In theory, this should never happen.
-			return err
-		}
-		rawConfig = enc
-	}
-
-	if am.configHash != md5.Sum(rawConfig) {
-		configChanged = true
-	}
-
-	if cfg.TemplateFiles == nil {
-		cfg.TemplateFiles = map[string]string{}
-	}
-	cfg.TemplateFiles["__default__.tmpl"] = channels.DefaultTemplateString
-
-	// next, we need to make sure we persist the templates to disk.
-	paths, templatesChanged, err := PersistTemplates(cfg, am.WorkingDirPath())
-	if err != nil {
-		return err
-	}
-
-	// If neither the configuration nor templates have changed, we've got nothing to do.
-	if !configChanged && !templatesChanged {
-		am.logger.Debug("neither config nor template have changed, skipping configuration sync.")
-		return nil
-	}
-
-	// With the templates persisted, create the template list using the paths.
-	tmpl, err := am.templateFromPaths(paths...)
-	if err != nil {
-		return err
-	}
-
-	// Finally, build the integrations map using the receiver configuration and templates.
-	integrationsMap, err := am.buildIntegrationsMap(cfg.AlertmanagerConfig.Receivers, tmpl)
-	if err != nil {
-		return fmt.Errorf("failed to build integration map: %w", err)
-	}
-
-	// Now, let's put together our notification pipeline
-	routingStage := make(notify.RoutingStage, len(integrationsMap))
-
-	if am.inhibitor != nil {
-		am.inhibitor.Stop()
-	}
-	if am.dispatcher != nil {
-		am.dispatcher.Stop()
-	}
-
-	am.inhibitor = inhibit.NewInhibitor(am.alerts, cfg.AlertmanagerConfig.InhibitRules, am.marker, am.logger)
-	am.muteTimes = am.buildMuteTimesMap(cfg.AlertmanagerConfig.MuteTimeIntervals)
-	am.silencer = silence.NewSilencer(am.silences, am.marker, am.logger)
-
-	meshStage := notify.NewGossipSettleStage(am.peer)
-	inhibitionStage := notify.NewMuteStage(am.inhibitor)
-	timeMuteStage := notify.NewTimeMuteStage(am.muteTimes)
-	silencingStage := notify.NewMuteStage(am.silencer)
-	for name := range integrationsMap {
-		stage := am.createReceiverStage(name, integrationsMap[name], am.waitFunc, am.notificationLog)
-		routingStage[name] = notify.MultiStage{meshStage, silencingStage, timeMuteStage, inhibitionStage, stage}
-	}
-
-	am.route = dispatch.NewRoute(cfg.AlertmanagerConfig.Route.AsAMRoute(), nil)
-	am.dispatcher = dispatch.NewDispatcher(am.alerts, am.route, routingStage, am.marker, am.timeoutFunc, &nilLimits{}, am.logger, am.dispatcherMetrics)
-
-	am.wg.Add(1)
-	go func() {
-		defer am.wg.Done()
-		am.dispatcher.Run()
-	}()
-
-	am.wg.Add(1)
-	go func() {
-		defer am.wg.Done()
-		am.inhibitor.Run()
-	}()
-
-	am.config = cfg
-	am.configHash = md5.Sum(rawConfig)
-
-	return nil
-}
-
-func (am *Alertmanager) WorkingDirPath() string {
-	return filepath.Join(am.Settings.DataPath, workingDir, strconv.Itoa(int(am.orgID)))
-}
-
-// buildIntegrationsMap builds a map of name to the list of Grafana integration notifiers off of a list of receiver config.
-func (am *Alertmanager) buildIntegrationsMap(receivers []*apimodels.PostableApiReceiver, templates *template.Template) (map[string][]notify.Integration, error) {
-	integrationsMap := make(map[string][]notify.Integration, len(receivers))
-	for _, receiver := range receivers {
-		integrations, err := am.buildReceiverIntegrations(receiver, templates)
-		if err != nil {
-			return nil, err
-		}
-		integrationsMap[receiver.Name] = integrations
-	}
-
-	return integrationsMap, nil
-}
-
-// buildReceiverIntegrations builds a list of integration notifiers off of a receiver config.
-func (am *Alertmanager) buildReceiverIntegrations(receiver *apimodels.PostableApiReceiver, tmpl *template.Template) ([]notify.Integration, error) {
-	var integrations []notify.Integration
-	for i, r := range receiver.GrafanaManagedReceivers {
-		n, err := am.buildReceiverIntegration(r, tmpl)
-		if err != nil {
-			return nil, err
-		}
-		integrations = append(integrations, notify.NewIntegration(n, n, r.Type, i))
-	}
-	return integrations, nil
-}
-
-func (am *Alertmanager) buildReceiverIntegration(r *apimodels.PostableGrafanaReceiver, tmpl *template.Template) (channels.NotificationChannel, error) {
-	// secure settings are already encrypted at this point
-	secureSettings := make(map[string][]byte, len(r.SecureSettings))
-
-	for k, v := range r.SecureSettings {
-		d, err := base64.StdEncoding.DecodeString(v)
-		if err != nil {
-			return nil, InvalidReceiverError{
-				Receiver: r,
-				Err:      errors.New("failed to decode secure setting"),
-			}
-		}
-		secureSettings[k] = d
-	}
-
-	var (
-		cfg = &channels.NotificationChannelConfig{
-			UID:                   r.UID,
-			OrgID:                 am.orgID,
-			Name:                  r.Name,
-			Type:                  r.Type,
-			DisableResolveMessage: r.DisableResolveMessage,
-			Settings:              r.Settings,
-			SecureSettings:        secureSettings,
-		}
-	)
-	factoryConfig, err := channels.NewFactoryConfig(cfg, am.NotificationService, am.decryptFn, tmpl, am.Store)
-	if err != nil {
-		return nil, InvalidReceiverError{
-			Receiver: r,
-			Err:      err,
-		}
-	}
-	receiverFactory, exists := channels.Factory(r.Type)
-	if !exists {
-		return nil, InvalidReceiverError{
-			Receiver: r,
-			Err:      fmt.Errorf("notifier %s is not supported", r.Type),
-		}
-	}
-	n, err := receiverFactory(factoryConfig)
-	if err != nil {
-		return nil, InvalidReceiverError{
-			Receiver: r,
-			Err:      err,
-		}
-	}
-	return n, nil
-}
-
-// PutAlerts receives the alerts and then sends them through the corresponding route based on whenever the alert has a receiver embedded or not
-func (am *Alertmanager) PutAlerts(postableAlerts apimodels.PostableAlerts) error {
-	now := time.Now()
-	alerts := make([]*types.Alert, 0, len(postableAlerts.PostableAlerts))
-	var validationErr *AlertValidationError
-	for _, a := range postableAlerts.PostableAlerts {
-		alert := &types.Alert{
-			Alert: model.Alert{
-				Labels:       model.LabelSet{},
-				Annotations:  model.LabelSet{},
-				StartsAt:     time.Time(a.StartsAt),
-				EndsAt:       time.Time(a.EndsAt),
-				GeneratorURL: a.GeneratorURL.String(),
-			},
-			UpdatedAt: now,
-		}
-
-		for k, v := range a.Labels {
-			if len(v) == 0 || k == ngmodels.NamespaceUIDLabel { // Skip empty and namespace UID labels.
-				continue
-			}
-			alert.Alert.Labels[model.LabelName(k)] = model.LabelValue(v)
-		}
-		for k, v := range a.Annotations {
-			if len(v) == 0 { // Skip empty annotation.
-				continue
-			}
-			alert.Alert.Annotations[model.LabelName(k)] = model.LabelValue(v)
-		}
-
-		// Ensure StartsAt is set.
-		if alert.StartsAt.IsZero() {
-			if alert.EndsAt.IsZero() {
-				alert.StartsAt = now
-			} else {
-				alert.StartsAt = alert.EndsAt
-			}
-		}
-		// If no end time is defined, set a timeout after which an alert
-		// is marked resolved if it is not updated.
-		if alert.EndsAt.IsZero() {
-			alert.Timeout = true
-			alert.EndsAt = now.Add(defaultResolveTimeout)
-		}
-
-		if alert.EndsAt.After(now) {
-			am.Metrics.Firing().Inc()
-		} else {
-			am.Metrics.Resolved().Inc()
-		}
-
-		if err := validateAlert(alert); err != nil {
-			if validationErr == nil {
-				validationErr = &AlertValidationError{}
-			}
-			validationErr.Alerts = append(validationErr.Alerts, a)
-			validationErr.Errors = append(validationErr.Errors, err)
-			am.Metrics.Invalid().Inc()
-			continue
-		}
-
-		alerts = append(alerts, alert)
-	}
-
-	if err := am.alerts.Put(alerts...); err != nil {
-		// Notification sending alert takes precedence over validation errors.
-		return err
-	}
-	if validationErr != nil {
-		// Even if validationErr is nil, the require.NoError fails on it.
-		return validationErr
-	}
-	return nil
-}
-
-// validateAlert is a.Validate() while additionally allowing
-// space for label and annotation names.
-func validateAlert(a *types.Alert) error {
-	if a.StartsAt.IsZero() {
-		return fmt.Errorf("start time missing")
-	}
-	if !a.EndsAt.IsZero() && a.EndsAt.Before(a.StartsAt) {
-		return fmt.Errorf("start time must be before end time")
-	}
-	if err := validateLabelSet(a.Labels); err != nil {
-		return fmt.Errorf("invalid label set: %s", err)
-	}
-	if len(a.Labels) == 0 {
-		return fmt.Errorf("at least one label pair required")
-	}
-	if err := validateLabelSet(a.Annotations); err != nil {
-		return fmt.Errorf("invalid annotations: %s", err)
-	}
-	return nil
-}
-
-// validateLabelSet is ls.Validate() while additionally allowing
-// space for label names.
-func validateLabelSet(ls model.LabelSet) error {
-	for ln, lv := range ls {
-		if !isValidLabelName(ln) {
-			return fmt.Errorf("invalid name %q", ln)
-		}
-		if !lv.IsValid() {
-			return fmt.Errorf("invalid value %q", lv)
-		}
-	}
-	return nil
-}
-
-// isValidLabelName is ln.IsValid() without restrictions other than it can not be empty.
-// The regex for Prometheus data model is ^[a-zA-Z_][a-zA-Z0-9_]*$.
-func isValidLabelName(ln model.LabelName) bool {
-	if len(ln) == 0 {
-		return false
-	}
-
-	return utf8.ValidString(string(ln))
-}
-
-// AlertValidationError is the error capturing the validation errors
-// faced on the alerts.
-type AlertValidationError struct {
-	Alerts []amv2.PostableAlert
-	Errors []error // Errors[i] refers to Alerts[i].
-}
-
-func (e AlertValidationError) Error() string {
-	errMsg := ""
-	if len(e.Errors) != 0 {
-		errMsg = e.Errors[0].Error()
-		for _, e := range e.Errors[1:] {
-			errMsg += ";" + e.Error()
-		}
-	}
-	return errMsg
-}
-
-// createReceiverStage creates a pipeline of stages for a receiver.
-func (am *Alertmanager) createReceiverStage(name string, integrations []notify.Integration, wait func() time.Duration, notificationLog notify.NotificationLog) notify.Stage {
-	var fs notify.FanoutStage
-	for i := range integrations {
-		recv := &nflogpb.Receiver{
-			GroupName:   name,
-			Integration: integrations[i].Name(),
-			Idx:         uint32(integrations[i].Index()),
-		}
-		var s notify.MultiStage
-		s = append(s, notify.NewWaitStage(wait))
-		s = append(s, notify.NewDedupStage(&integrations[i], notificationLog, recv))
-		s = append(s, notify.NewRetryStage(integrations[i], name, am.stageMetrics))
-		s = append(s, notify.NewSetNotifiesStage(notificationLog, recv))
-
-		fs = append(fs, s)
-	}
-	return fs
-}
-
-func (am *Alertmanager) waitFunc() time.Duration {
-	return time.Duration(am.peer.Position()) * am.peerTimeout
-}
-
-func (am *Alertmanager) timeoutFunc(d time.Duration) time.Duration {
-	// time.Duration d relates to the receiver's group_interval. Even with a group interval of 1s,
-	// we need to make sure (non-position-0) peers in the cluster wait before flushing the notifications.
-	if d < notify.MinTimeout {
-		d = notify.MinTimeout
-	}
-	return d + am.waitFunc()
-}
-
-type nilLimits struct{}
-
-func (n nilLimits) MaxNumberOfAggregationGroups() int { return 0 }
diff --git a/alerting/alertmanager_config.go b/alerting/alertmanager_config.go
index e564813f..7afbbb34 100644
--- a/alerting/alertmanager_config.go
+++ b/alerting/alertmanager_config.go
@@ -1,4 +1,4 @@
-package notifier
+package alerting
 
 import (
 	"context"
diff --git a/alerting/alerts.go b/alerting/alerts.go
index 0bc795d9..b94496a5 100644
--- a/alerting/alerts.go
+++ b/alerting/alerts.go
@@ -1,4 +1,4 @@
-package notifier
+package alerting
 
 import (
 	"fmt"
diff --git a/alerting/available_channels.go b/alerting/available_channels.go
index 48c82c7b..609bd9ab 100644
--- a/alerting/available_channels.go
+++ b/alerting/available_channels.go
@@ -1,4 +1,4 @@
-package notifier
+package alerting
 
 import (
 	"github.com/grafana/grafana/pkg/services/alerting"
diff --git a/alerting/config.go b/alerting/config.go
index 1879773b..04c6ab57 100644
--- a/alerting/config.go
+++ b/alerting/config.go
@@ -1,4 +1,4 @@
-package notifier
+package alerting
 
 import (
 	"encoding/json"
diff --git a/alerting/config_test.go b/alerting/config_test.go
index a987dfc8..b5a682d1 100644
--- a/alerting/config_test.go
+++ b/alerting/config_test.go
@@ -1,4 +1,4 @@
-package notifier
+package alerting
 
 import (
 	"errors"
diff --git a/alerting/crypto.go b/alerting/crypto.go
index 97a97525..7f1bdd69 100644
--- a/alerting/crypto.go
+++ b/alerting/crypto.go
@@ -1,4 +1,4 @@
-package notifier
+package alerting
 
 import (
 	"context"
diff --git a/alerting/file_store.go b/alerting/file_store.go
index 42ec6e20..7ab40e14 100644
--- a/alerting/file_store.go
+++ b/alerting/file_store.go
@@ -1,4 +1,4 @@
-package notifier
+package alerting
 
 import (
 	"context"
diff --git a/alerting/file_store_test.go b/alerting/file_store_test.go
index b6268a6d..306694d4 100644
--- a/alerting/file_store_test.go
+++ b/alerting/file_store_test.go
@@ -1,4 +1,4 @@
-package notifier
+package alerting
 
 import (
 	"context"
diff --git a/alerting/grafana_alertmanager.go b/alerting/grafana_alertmanager.go
index cc636c62..ac33e63a 100644
--- a/alerting/grafana_alertmanager.go
+++ b/alerting/grafana_alertmanager.go
@@ -145,6 +145,7 @@ type GrafanaAlertmanagerConfig struct {
 
 func NewGrafanaAlertmanager(ctx context.Context, orgID int64, cfg *setting.Cfg, store AlertingStore, config *GrafanaAlertmanagerConfig,
 	peer ClusterPeer, decryptFn channels.GetDecryptedValueFn, ns notifications.Service, m *metrics.Alertmanager) (*GrafanaAlertmanager, error) {
+
 	am := &GrafanaAlertmanager{
 		Settings:            cfg,
 		stopc:               make(chan struct{}),
diff --git a/alerting/alertmanager_test.go b/alerting/grafana_alertmanager_test.go
similarity index 99%
rename from alerting/alertmanager_test.go
rename to alerting/grafana_alertmanager_test.go
index c308e800..a39cba8d 100644
--- a/alerting/alertmanager_test.go
+++ b/alerting/grafana_alertmanager_test.go
@@ -1,4 +1,4 @@
-package notifier
+package alerting
 
 import (
 	"context"
diff --git a/alerting/multiorg_alertmanager.go b/alerting/multiorg_alertmanager.go
index 0d5475b0..f9c4235d 100644
--- a/alerting/multiorg_alertmanager.go
+++ b/alerting/multiorg_alertmanager.go
@@ -1,4 +1,4 @@
-package notifier
+package alerting
 
 import (
 	"context"
diff --git a/alerting/multiorg_alertmanager_test.go b/alerting/multiorg_alertmanager_test.go
index d0f81977..ad770f14 100644
--- a/alerting/multiorg_alertmanager_test.go
+++ b/alerting/multiorg_alertmanager_test.go
@@ -1,4 +1,4 @@
-package notifier
+package alerting
 
 import (
 	"bytes"
diff --git a/alerting/receivers.go b/alerting/receivers.go
index 1b60a727..015e6133 100644
--- a/alerting/receivers.go
+++ b/alerting/receivers.go
@@ -1,4 +1,4 @@
-package notifier
+package alerting
 
 import (
 	"context"
diff --git a/alerting/receivers_test.go b/alerting/receivers_test.go
index 136d3eeb..b2ddb406 100644
--- a/alerting/receivers_test.go
+++ b/alerting/receivers_test.go
@@ -1,4 +1,4 @@
-package notifier
+package alerting
 
 import (
 	"context"
diff --git a/alerting/silences.go b/alerting/silences.go
index 27a9cd76..89077552 100644
--- a/alerting/silences.go
+++ b/alerting/silences.go
@@ -1,4 +1,4 @@
-package notifier
+package alerting
 
 import (
 	"errors"
diff --git a/alerting/status.go b/alerting/status.go
index eef11ab4..65acbfa0 100644
--- a/alerting/status.go
+++ b/alerting/status.go
@@ -1,4 +1,4 @@
-package notifier
+package alerting
 
 import (
 	apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
diff --git a/alerting/testing.go b/alerting/testing.go
index 3415569b..616c60e4 100644
--- a/alerting/testing.go
+++ b/alerting/testing.go
@@ -1,4 +1,4 @@
-package notifier
+package alerting
 
 import (
 	"context"