Chore: Remove result fields from ngalert (#65410)

* remove result fields from ngalert

* remove duplicate imports
This commit is contained in:
Serge Zaitsev 2023-03-28 10:34:35 +02:00 committed by GitHub
parent 42b58fbca6
commit 0beb768427
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 307 additions and 317 deletions

View File

@ -55,7 +55,7 @@ type Alertmanager interface {
} }
type AlertingStore interface { type AlertingStore interface {
GetLatestAlertmanagerConfiguration(ctx context.Context, query *models.GetLatestAlertmanagerConfigurationQuery) error GetLatestAlertmanagerConfiguration(ctx context.Context, query *models.GetLatestAlertmanagerConfigurationQuery) (*models.AlertConfiguration, error)
} }
// API handlers. // API handlers.

View File

@ -150,7 +150,8 @@ func (srv PrometheusSrv) RouteGetRuleStatuses(c *contextmodel.ReqContext) respon
DashboardUID: dashboardUID, DashboardUID: dashboardUID,
PanelID: panelID, PanelID: panelID,
} }
if err := srv.store.ListAlertRules(c.Req.Context(), &alertRuleQuery); err != nil { ruleList, err := srv.store.ListAlertRules(c.Req.Context(), &alertRuleQuery)
if err != nil {
ruleResponse.DiscoveryBase.Status = "error" ruleResponse.DiscoveryBase.Status = "error"
ruleResponse.DiscoveryBase.Error = fmt.Sprintf("failure getting rules: %s", err.Error()) ruleResponse.DiscoveryBase.Error = fmt.Sprintf("failure getting rules: %s", err.Error())
ruleResponse.DiscoveryBase.ErrorType = apiv1.ErrServer ruleResponse.DiscoveryBase.ErrorType = apiv1.ErrServer
@ -161,7 +162,7 @@ func (srv PrometheusSrv) RouteGetRuleStatuses(c *contextmodel.ReqContext) respon
} }
groupedRules := make(map[ngmodels.AlertRuleGroupKey][]*ngmodels.AlertRule) groupedRules := make(map[ngmodels.AlertRuleGroupKey][]*ngmodels.AlertRule)
for _, rule := range alertRuleQuery.Result { for _, rule := range ruleList {
key := rule.GetGroupKey() key := rule.GetGroupKey()
rulesInGroup := groupedRules[key] rulesInGroup := groupedRules[key]
rulesInGroup = append(rulesInGroup, rule) rulesInGroup = append(rulesInGroup, rule)

View File

@ -83,21 +83,22 @@ func (srv RulerSrv) RouteDeleteAlertRules(c *contextmodel.ReqContext, namespaceT
NamespaceUIDs: []string{namespace.UID}, NamespaceUIDs: []string{namespace.UID},
RuleGroup: ruleGroup, RuleGroup: ruleGroup,
} }
if err = srv.store.ListAlertRules(ctx, &q); err != nil { ruleList, err := srv.store.ListAlertRules(ctx, &q)
if err != nil {
return err return err
} }
if len(q.Result) == 0 { if len(ruleList) == 0 {
logger.Debug("no alert rules to delete from namespace/group") logger.Debug("no alert rules to delete from namespace/group")
return nil return nil
} }
var deletionCandidates = make(map[ngmodels.AlertRuleGroupKey][]*ngmodels.AlertRule) var deletionCandidates = make(map[ngmodels.AlertRuleGroupKey][]*ngmodels.AlertRule)
for _, rule := range q.Result { for _, rule := range ruleList {
key := rule.GetGroupKey() key := rule.GetGroupKey()
deletionCandidates[key] = append(deletionCandidates[key], rule) deletionCandidates[key] = append(deletionCandidates[key], rule)
} }
rulesToDelete := make([]string, 0, len(q.Result)) rulesToDelete := make([]string, 0, len(ruleList))
for groupKey, rules := range deletionCandidates { for groupKey, rules := range deletionCandidates {
if !authorizeAccessToRuleGroup(rules, hasAccess) { if !authorizeAccessToRuleGroup(rules, hasAccess) {
unauthz = true unauthz = true
@ -156,7 +157,8 @@ func (srv RulerSrv) RouteGetNamespaceRulesConfig(c *contextmodel.ReqContext, nam
OrgID: c.SignedInUser.OrgID, OrgID: c.SignedInUser.OrgID,
NamespaceUIDs: []string{namespace.UID}, NamespaceUIDs: []string{namespace.UID},
} }
if err := srv.store.ListAlertRules(c.Req.Context(), &q); err != nil { ruleList, err := srv.store.ListAlertRules(c.Req.Context(), &q)
if err != nil {
return ErrResp(http.StatusInternalServerError, err, "failed to update rule group") return ErrResp(http.StatusInternalServerError, err, "failed to update rule group")
} }
@ -172,7 +174,7 @@ func (srv RulerSrv) RouteGetNamespaceRulesConfig(c *contextmodel.ReqContext, nam
} }
ruleGroups := make(map[string]ngmodels.RulesGroup) ruleGroups := make(map[string]ngmodels.RulesGroup)
for _, r := range q.Result { for _, r := range ruleList {
ruleGroups[r.RuleGroup] = append(ruleGroups[r.RuleGroup], r) ruleGroups[r.RuleGroup] = append(ruleGroups[r.RuleGroup], r)
} }
@ -199,7 +201,8 @@ func (srv RulerSrv) RouteGetRulesGroupConfig(c *contextmodel.ReqContext, namespa
NamespaceUIDs: []string{namespace.UID}, NamespaceUIDs: []string{namespace.UID},
RuleGroup: ruleGroup, RuleGroup: ruleGroup,
} }
if err := srv.store.ListAlertRules(c.Req.Context(), &q); err != nil { ruleList, err := srv.store.ListAlertRules(c.Req.Context(), &q)
if err != nil {
return ErrResp(http.StatusInternalServerError, err, "failed to get group alert rules") return ErrResp(http.StatusInternalServerError, err, "failed to get group alert rules")
} }
@ -212,12 +215,12 @@ func (srv RulerSrv) RouteGetRulesGroupConfig(c *contextmodel.ReqContext, namespa
return ErrResp(http.StatusInternalServerError, err, "failed to get group alert rules") return ErrResp(http.StatusInternalServerError, err, "failed to get group alert rules")
} }
if !authorizeAccessToRuleGroup(q.Result, hasAccess) { if !authorizeAccessToRuleGroup(ruleList, hasAccess) {
return ErrResp(http.StatusUnauthorized, fmt.Errorf("%w to access the group because it does not have access to one or many data sources one or many rules in the group use", ErrAuthorization), "") return ErrResp(http.StatusUnauthorized, fmt.Errorf("%w to access the group because it does not have access to one or many data sources one or many rules in the group use", ErrAuthorization), "")
} }
result := apimodels.RuleGroupConfigResponse{ result := apimodels.RuleGroupConfigResponse{
GettableRuleGroupConfig: toGettableRuleGroupConfig(ruleGroup, q.Result, namespace.ID, provenanceRecords), GettableRuleGroupConfig: toGettableRuleGroupConfig(ruleGroup, ruleList, namespace.ID, provenanceRecords),
} }
return response.JSON(http.StatusAccepted, result) return response.JSON(http.StatusAccepted, result)
} }
@ -256,7 +259,8 @@ func (srv RulerSrv) RouteGetRulesConfig(c *contextmodel.ReqContext) response.Res
PanelID: panelID, PanelID: panelID,
} }
if err := srv.store.ListAlertRules(c.Req.Context(), &q); err != nil { ruleList, err := srv.store.ListAlertRules(c.Req.Context(), &q)
if err != nil {
return ErrResp(http.StatusInternalServerError, err, "failed to get alert rules") return ErrResp(http.StatusInternalServerError, err, "failed to get alert rules")
} }
@ -270,7 +274,7 @@ func (srv RulerSrv) RouteGetRulesConfig(c *contextmodel.ReqContext) response.Res
} }
configs := make(map[ngmodels.AlertRuleGroupKey]ngmodels.RulesGroup) configs := make(map[ngmodels.AlertRuleGroupKey]ngmodels.RulesGroup)
for _, r := range q.Result { for _, r := range ruleList {
groupKey := r.GetGroupKey() groupKey := r.GetGroupKey()
group := configs[groupKey] group := configs[groupKey]
group = append(group, r) group = append(group, r)

View File

@ -12,8 +12,8 @@ import (
type RuleStore interface { type RuleStore interface {
GetUserVisibleNamespaces(context.Context, int64, *user.SignedInUser) (map[string]*folder.Folder, error) GetUserVisibleNamespaces(context.Context, int64, *user.SignedInUser) (map[string]*folder.Folder, error)
GetNamespaceByTitle(context.Context, string, int64, *user.SignedInUser, bool) (*folder.Folder, error) GetNamespaceByTitle(context.Context, string, int64, *user.SignedInUser, bool) (*folder.Folder, error)
GetAlertRulesGroupByRuleUID(ctx context.Context, query *ngmodels.GetAlertRulesGroupByRuleUIDQuery) error GetAlertRulesGroupByRuleUID(ctx context.Context, query *ngmodels.GetAlertRulesGroupByRuleUIDQuery) ([]*ngmodels.AlertRule, error)
ListAlertRules(ctx context.Context, query *ngmodels.ListAlertRulesQuery) error ListAlertRules(ctx context.Context, query *ngmodels.ListAlertRulesQuery) (ngmodels.RulesGroup, error)
// InsertAlertRules will insert all alert rules passed into the function // InsertAlertRules will insert all alert rules passed into the function
// and return the map of uuid to id. // and return the map of uuid to id.

View File

@ -362,16 +362,12 @@ type AlertRuleVersion struct {
type GetAlertRuleByUIDQuery struct { type GetAlertRuleByUIDQuery struct {
UID string UID string
OrgID int64 OrgID int64
Result *AlertRule
} }
// GetAlertRulesGroupByRuleUIDQuery is the query for retrieving a group of alerts by UID of a rule that belongs to that group // GetAlertRulesGroupByRuleUIDQuery is the query for retrieving a group of alerts by UID of a rule that belongs to that group
type GetAlertRulesGroupByRuleUIDQuery struct { type GetAlertRulesGroupByRuleUIDQuery struct {
UID string UID string
OrgID int64 OrgID int64
Result []*AlertRule
} }
// ListAlertRulesQuery is the query for listing alert rules // ListAlertRulesQuery is the query for listing alert rules
@ -385,8 +381,6 @@ type ListAlertRulesQuery struct {
// to return just those for a dashboard and panel. // to return just those for a dashboard and panel.
DashboardUID string DashboardUID string
PanelID int64 PanelID int64
Result RulesGroup
} }
// CountAlertRulesQuery is the query for counting alert rules // CountAlertRulesQuery is the query for counting alert rules
@ -407,8 +401,6 @@ type ListNamespaceAlertRulesQuery struct {
OrgID int64 OrgID int64
// Namespace is the folder slug // Namespace is the folder slug
NamespaceUID string NamespaceUID string
Result []*AlertRule
} }
// ListOrgRuleGroupsQuery is the query for listing unique rule groups // ListOrgRuleGroupsQuery is the query for listing unique rule groups
@ -421,8 +413,6 @@ type ListOrgRuleGroupsQuery struct {
// to return just those for a dashboard and panel. // to return just those for a dashboard and panel.
DashboardUID string DashboardUID string
PanelID int64 PanelID int64
Result [][]string
} }
type UpdateRule struct { type UpdateRule struct {

View File

@ -25,8 +25,7 @@ type HistoricAlertConfiguration struct {
// GetLatestAlertmanagerConfigurationQuery is the query to get the latest alertmanager configuration. // GetLatestAlertmanagerConfigurationQuery is the query to get the latest alertmanager configuration.
type GetLatestAlertmanagerConfigurationQuery struct { type GetLatestAlertmanagerConfigurationQuery struct {
OrgID int64 OrgID int64
Result *AlertConfiguration
} }
// SaveAlertmanagerConfigurationCmd is the command to save an alertmanager configuration. // SaveAlertmanagerConfigurationCmd is the command to save an alertmanager configuration.
@ -47,8 +46,7 @@ type MarkConfigurationAsAppliedCmd struct {
// GetAppliedConfigurationsQuery is the query for getting configurations that have been previously applied with no errors. // GetAppliedConfigurationsQuery is the query for getting configurations that have been previously applied with no errors.
type GetAppliedConfigurationsQuery struct { type GetAppliedConfigurationsQuery struct {
OrgID int64 OrgID int64
Result []*HistoricAlertConfiguration
} }
func HistoricConfigFromAlertConfig(config AlertConfiguration) HistoricAlertConfiguration { func HistoricConfigFromAlertConfig(config AlertConfiguration) HistoricAlertConfiguration {

View File

@ -52,8 +52,6 @@ func (i InstanceStateType) IsValid() bool {
type ListAlertInstancesQuery struct { type ListAlertInstancesQuery struct {
RuleUID string RuleUID string
RuleOrgID int64 `json:"-"` RuleOrgID int64 `json:"-"`
Result []*AlertInstance
} }
// ValidateAlertInstance validates that the alert instance contains an alert rule id, // ValidateAlertInstance validates that the alert instance contains an alert rule id,

View File

@ -28,16 +28,16 @@ func (e AlertmanagerConfigRejectedError) Error() string {
} }
type configurationStore interface { type configurationStore interface {
GetLatestAlertmanagerConfiguration(ctx context.Context, query *models.GetLatestAlertmanagerConfigurationQuery) error GetLatestAlertmanagerConfiguration(ctx context.Context, query *models.GetLatestAlertmanagerConfigurationQuery) (*models.AlertConfiguration, error)
} }
func (moa *MultiOrgAlertmanager) GetAlertmanagerConfiguration(ctx context.Context, org int64) (definitions.GettableUserConfig, error) { func (moa *MultiOrgAlertmanager) GetAlertmanagerConfiguration(ctx context.Context, org int64) (definitions.GettableUserConfig, error) {
query := models.GetLatestAlertmanagerConfigurationQuery{OrgID: org} query := models.GetLatestAlertmanagerConfigurationQuery{OrgID: org}
err := moa.configStore.GetLatestAlertmanagerConfiguration(ctx, &query) amConfig, err := moa.configStore.GetLatestAlertmanagerConfiguration(ctx, &query)
if err != nil { if err != nil {
return definitions.GettableUserConfig{}, fmt.Errorf("failed to get latest configuration: %w", err) return definitions.GettableUserConfig{}, fmt.Errorf("failed to get latest configuration: %w", err)
} }
cfg, err := Load([]byte(query.Result.AlertmanagerConfiguration)) cfg, err := Load([]byte(amConfig.AlertmanagerConfiguration))
if err != nil { if err != nil {
return definitions.GettableUserConfig{}, fmt.Errorf("failed to unmarshal alertmanager configuration: %w", err) return definitions.GettableUserConfig{}, fmt.Errorf("failed to unmarshal alertmanager configuration: %w", err)
} }
@ -93,7 +93,8 @@ func (moa *MultiOrgAlertmanager) GetAlertmanagerConfiguration(ctx context.Contex
func (moa *MultiOrgAlertmanager) ApplyAlertmanagerConfiguration(ctx context.Context, org int64, config definitions.PostableUserConfig) error { func (moa *MultiOrgAlertmanager) ApplyAlertmanagerConfiguration(ctx context.Context, org int64, config definitions.PostableUserConfig) error {
// Get the last known working configuration // Get the last known working configuration
query := models.GetLatestAlertmanagerConfigurationQuery{OrgID: org} query := models.GetLatestAlertmanagerConfigurationQuery{OrgID: org}
if err := moa.configStore.GetLatestAlertmanagerConfiguration(ctx, &query); err != nil { _, err := moa.configStore.GetLatestAlertmanagerConfiguration(ctx, &query)
if 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 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) { if !errors.Is(err, store.ErrNoAlertmanagerConfiguration) {
return fmt.Errorf("failed to get latest configuration %w", err) return fmt.Errorf("failed to get latest configuration %w", err)

View File

@ -40,7 +40,8 @@ func NewCrypto(secrets secrets.Service, configs configurationStore, log log.Logg
func (c *alertmanagerCrypto) LoadSecureSettings(ctx context.Context, orgId int64, receivers []*definitions.PostableApiReceiver) error { func (c *alertmanagerCrypto) LoadSecureSettings(ctx context.Context, orgId int64, receivers []*definitions.PostableApiReceiver) error {
// Get the last known working configuration. // Get the last known working configuration.
query := models.GetLatestAlertmanagerConfigurationQuery{OrgID: orgId} query := models.GetLatestAlertmanagerConfigurationQuery{OrgID: orgId}
if err := c.configs.GetLatestAlertmanagerConfiguration(ctx, &query); err != nil { amConfig, err := c.configs.GetLatestAlertmanagerConfiguration(ctx, &query)
if 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 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) { if !errors.Is(err, store.ErrNoAlertmanagerConfiguration) {
return fmt.Errorf("failed to get latest configuration: %w", err) return fmt.Errorf("failed to get latest configuration: %w", err)
@ -48,8 +49,8 @@ func (c *alertmanagerCrypto) LoadSecureSettings(ctx context.Context, orgId int64
} }
currentReceiverMap := make(map[string]*definitions.PostableGrafanaReceiver) currentReceiverMap := make(map[string]*definitions.PostableGrafanaReceiver)
if query.Result != nil { if amConfig != nil {
currentConfig, err := Load([]byte(query.Result.AlertmanagerConfiguration)) currentConfig, err := Load([]byte(amConfig.AlertmanagerConfiguration))
// If the current config is un-loadable, treat it as if it never existed. Providing a new, valid config should be able to "fix" this state. // If the current config is un-loadable, treat it as if it never existed. Providing a new, valid config should be able to "fix" this state.
if err != nil { if err != nil {
c.log.Warn("last known alertmanager configuration was invalid. Overwriting...") c.log.Warn("last known alertmanager configuration was invalid. Overwriting...")

View File

@ -51,14 +51,12 @@ func (f *fakeConfigStore) GetAllLatestAlertmanagerConfiguration(context.Context)
return result, nil return result, nil
} }
func (f *fakeConfigStore) GetLatestAlertmanagerConfiguration(_ context.Context, query *models.GetLatestAlertmanagerConfigurationQuery) error { func (f *fakeConfigStore) GetLatestAlertmanagerConfiguration(_ context.Context, query *models.GetLatestAlertmanagerConfigurationQuery) (*models.AlertConfiguration, error) {
var ok bool config, ok := f.configs[query.OrgID]
query.Result, ok = f.configs[query.OrgID]
if !ok { if !ok {
return store.ErrNoAlertmanagerConfiguration return nil, store.ErrNoAlertmanagerConfiguration
} }
return config, nil
return nil
} }
func (f *fakeConfigStore) SaveAlertmanagerConfiguration(ctx context.Context, cmd *models.SaveAlertmanagerConfigurationCmd) error { func (f *fakeConfigStore) SaveAlertmanagerConfiguration(ctx context.Context, cmd *models.SaveAlertmanagerConfigurationCmd) error {

View File

@ -51,12 +51,12 @@ func (service *AlertRuleService) GetAlertRules(ctx context.Context, orgID int64)
q := models.ListAlertRulesQuery{ q := models.ListAlertRulesQuery{
OrgID: orgID, OrgID: orgID,
} }
err := service.ruleStore.ListAlertRules(ctx, &q) rules, err := service.ruleStore.ListAlertRules(ctx, &q)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// TODO: GET provenance // TODO: GET provenance
return q.Result, nil return rules, nil
} }
func (service *AlertRuleService) GetAlertRule(ctx context.Context, orgID int64, ruleUID string) (models.AlertRule, models.Provenance, error) { func (service *AlertRuleService) GetAlertRule(ctx context.Context, orgID int64, ruleUID string) (models.AlertRule, models.Provenance, error) {
@ -64,15 +64,15 @@ func (service *AlertRuleService) GetAlertRule(ctx context.Context, orgID int64,
OrgID: orgID, OrgID: orgID,
UID: ruleUID, UID: ruleUID,
} }
err := service.ruleStore.GetAlertRuleByUID(ctx, query) rules, err := service.ruleStore.GetAlertRuleByUID(ctx, query)
if err != nil { if err != nil {
return models.AlertRule{}, models.ProvenanceNone, err return models.AlertRule{}, models.ProvenanceNone, err
} }
provenance, err := service.provenanceStore.GetProvenance(ctx, query.Result, orgID) provenance, err := service.provenanceStore.GetProvenance(ctx, rules, orgID)
if err != nil { if err != nil {
return models.AlertRule{}, models.ProvenanceNone, err return models.AlertRule{}, models.ProvenanceNone, err
} }
return *query.Result, provenance, nil return *rules, provenance, nil
} }
type AlertRuleWithFolderTitle struct { type AlertRuleWithFolderTitle struct {
@ -86,14 +86,14 @@ func (service *AlertRuleService) GetAlertRuleWithFolderTitle(ctx context.Context
OrgID: orgID, OrgID: orgID,
UID: ruleUID, UID: ruleUID,
} }
err := service.ruleStore.GetAlertRuleByUID(ctx, query) rule, err := service.ruleStore.GetAlertRuleByUID(ctx, query)
if err != nil { if err != nil {
return AlertRuleWithFolderTitle{}, err return AlertRuleWithFolderTitle{}, err
} }
dq := dashboards.GetDashboardQuery{ dq := dashboards.GetDashboardQuery{
OrgID: orgID, OrgID: orgID,
UID: query.Result.NamespaceUID, UID: rule.NamespaceUID,
} }
dash, err := service.dashboardService.GetDashboard(ctx, &dq) dash, err := service.dashboardService.GetDashboard(ctx, &dq)
@ -102,7 +102,7 @@ func (service *AlertRuleService) GetAlertRuleWithFolderTitle(ctx context.Context
} }
return AlertRuleWithFolderTitle{ return AlertRuleWithFolderTitle{
AlertRule: *query.Result, AlertRule: *rule,
FolderTitle: dash.Title, FolderTitle: dash.Title,
}, nil }, nil
} }
@ -158,19 +158,20 @@ func (service *AlertRuleService) GetRuleGroup(ctx context.Context, orgID int64,
NamespaceUIDs: []string{namespaceUID}, NamespaceUIDs: []string{namespaceUID},
RuleGroup: group, RuleGroup: group,
} }
if err := service.ruleStore.ListAlertRules(ctx, &q); err != nil { ruleList, err := service.ruleStore.ListAlertRules(ctx, &q)
if err != nil {
return models.AlertRuleGroup{}, err return models.AlertRuleGroup{}, err
} }
if len(q.Result) == 0 { if len(ruleList) == 0 {
return models.AlertRuleGroup{}, store.ErrAlertRuleGroupNotFound return models.AlertRuleGroup{}, store.ErrAlertRuleGroupNotFound
} }
res := models.AlertRuleGroup{ res := models.AlertRuleGroup{
Title: q.Result[0].RuleGroup, Title: ruleList[0].RuleGroup,
FolderUID: q.Result[0].NamespaceUID, FolderUID: ruleList[0].NamespaceUID,
Interval: q.Result[0].IntervalSeconds, Interval: ruleList[0].IntervalSeconds,
Rules: []models.AlertRule{}, Rules: []models.AlertRule{},
} }
for _, r := range q.Result { for _, r := range ruleList {
if r != nil { if r != nil {
res.Rules = append(res.Rules, *r) res.Rules = append(res.Rules, *r)
} }
@ -189,12 +190,12 @@ func (service *AlertRuleService) UpdateRuleGroup(ctx context.Context, orgID int6
NamespaceUIDs: []string{namespaceUID}, NamespaceUIDs: []string{namespaceUID},
RuleGroup: ruleGroup, RuleGroup: ruleGroup,
} }
err := service.ruleStore.ListAlertRules(ctx, query) ruleList, err := service.ruleStore.ListAlertRules(ctx, query)
if err != nil { if err != nil {
return fmt.Errorf("failed to list alert rules: %w", err) return fmt.Errorf("failed to list alert rules: %w", err)
} }
updateRules := make([]models.UpdateRule, 0, len(query.Result)) updateRules := make([]models.UpdateRule, 0, len(ruleList))
for _, rule := range query.Result { for _, rule := range ruleList {
if rule.IntervalSeconds == intervalSeconds { if rule.IntervalSeconds == intervalSeconds {
continue continue
} }
@ -222,11 +223,12 @@ func (service *AlertRuleService) ReplaceRuleGroup(ctx context.Context, orgID int
NamespaceUIDs: []string{group.FolderUID}, NamespaceUIDs: []string{group.FolderUID},
RuleGroup: group.Title, RuleGroup: group.Title,
} }
if err := service.ruleStore.ListAlertRules(ctx, &listRulesQuery); err != nil { ruleList, err := service.ruleStore.ListAlertRules(ctx, &listRulesQuery)
if err != nil {
return fmt.Errorf("failed to list alert rules: %w", err) return fmt.Errorf("failed to list alert rules: %w", err)
} }
group.Rules = make([]models.AlertRule, 0, len(listRulesQuery.Result)) group.Rules = make([]models.AlertRule, 0, len(ruleList))
for _, r := range listRulesQuery.Result { for _, r := range ruleList {
if r != nil { if r != nil {
group.Rules = append(group.Rules, *r) group.Rules = append(group.Rules, *r)
} }
@ -411,10 +413,11 @@ func (service *AlertRuleService) GetAlertRuleGroupWithFolderTitle(ctx context.Co
NamespaceUIDs: []string{namespaceUID}, NamespaceUIDs: []string{namespaceUID},
RuleGroup: group, RuleGroup: group,
} }
if err := service.ruleStore.ListAlertRules(ctx, &q); err != nil { ruleList, err := service.ruleStore.ListAlertRules(ctx, &q)
if err != nil {
return file.AlertRuleGroupWithFolderTitle{}, err return file.AlertRuleGroupWithFolderTitle{}, err
} }
if len(q.Result) == 0 { if len(ruleList) == 0 {
return file.AlertRuleGroupWithFolderTitle{}, store.ErrAlertRuleGroupNotFound return file.AlertRuleGroupWithFolderTitle{}, store.ErrAlertRuleGroupNotFound
} }
@ -429,15 +432,15 @@ func (service *AlertRuleService) GetAlertRuleGroupWithFolderTitle(ctx context.Co
res := file.AlertRuleGroupWithFolderTitle{ res := file.AlertRuleGroupWithFolderTitle{
AlertRuleGroup: &models.AlertRuleGroup{ AlertRuleGroup: &models.AlertRuleGroup{
Title: q.Result[0].RuleGroup, Title: ruleList[0].RuleGroup,
FolderUID: q.Result[0].NamespaceUID, FolderUID: ruleList[0].NamespaceUID,
Interval: q.Result[0].IntervalSeconds, Interval: ruleList[0].IntervalSeconds,
Rules: []models.AlertRule{}, Rules: []models.AlertRule{},
}, },
OrgID: orgID, OrgID: orgID,
FolderTitle: dash.Title, FolderTitle: dash.Title,
} }
for _, r := range q.Result { for _, r := range ruleList {
if r != nil { if r != nil {
res.AlertRuleGroup.Rules = append(res.AlertRuleGroup.Rules, *r) res.AlertRuleGroup.Rules = append(res.AlertRuleGroup.Rules, *r)
} }
@ -451,13 +454,14 @@ func (service *AlertRuleService) GetAlertGroupsWithFolderTitle(ctx context.Conte
OrgID: orgID, OrgID: orgID,
} }
if err := service.ruleStore.ListAlertRules(ctx, &q); err != nil { ruleList, err := service.ruleStore.ListAlertRules(ctx, &q)
if err != nil {
return nil, err return nil, err
} }
groups := make(map[models.AlertRuleGroupKey][]models.AlertRule) groups := make(map[models.AlertRuleGroupKey][]models.AlertRule)
namespaces := make(map[string][]*models.AlertRuleGroupKey) namespaces := make(map[string][]*models.AlertRuleGroupKey)
for _, r := range q.Result { for _, r := range ruleList {
groupKey := r.GetGroupKey() groupKey := r.GetGroupKey()
group := groups[groupKey] group := groups[groupKey]
group = append(group, *r) group = append(group, *r)

View File

@ -31,16 +31,17 @@ func getLastConfiguration(ctx context.Context, orgID int64, store AMConfigStore)
q := models.GetLatestAlertmanagerConfigurationQuery{ q := models.GetLatestAlertmanagerConfigurationQuery{
OrgID: orgID, OrgID: orgID,
} }
if err := store.GetLatestAlertmanagerConfiguration(ctx, &q); err != nil { alertManagerConfig, err := store.GetLatestAlertmanagerConfiguration(ctx, &q)
if err != nil {
return nil, err return nil, err
} }
if q.Result == nil { if alertManagerConfig == nil {
return nil, fmt.Errorf("no alertmanager configuration present in this org") return nil, fmt.Errorf("no alertmanager configuration present in this org")
} }
concurrencyToken := q.Result.ConfigurationHash concurrencyToken := alertManagerConfig.ConfigurationHash
cfg, err := deserializeAlertmanagerConfig([]byte(q.Result.AlertmanagerConfiguration)) cfg, err := deserializeAlertmanagerConfig([]byte(alertManagerConfig.AlertmanagerConfiguration))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -48,6 +49,6 @@ func getLastConfiguration(ctx context.Context, orgID int64, store AMConfigStore)
return &cfgRevision{ return &cfgRevision{
cfg: cfg, cfg: cfg,
concurrencyToken: concurrencyToken, concurrencyToken: concurrencyToken,
version: q.Result.ConfigurationVersion, version: alertManagerConfig.ConfigurationVersion,
}, nil }, nil
} }

View File

@ -224,9 +224,9 @@ func TestContactPointService(t *testing.T) {
q := models.GetLatestAlertmanagerConfigurationQuery{ q := models.GetLatestAlertmanagerConfigurationQuery{
OrgID: 1, OrgID: 1,
} }
err := sut.amStore.GetLatestAlertmanagerConfiguration(context.Background(), &q) config, err := sut.amStore.GetLatestAlertmanagerConfiguration(context.Background(), &q)
require.NoError(t, err) require.NoError(t, err)
expectedConcurrencyToken := q.Result.ConfigurationHash expectedConcurrencyToken := config.ConfigurationHash
_, err = sut.CreateContactPoint(context.Background(), 1, newCp, models.ProvenanceAPI) _, err = sut.CreateContactPoint(context.Background(), 1, newCp, models.ProvenanceAPI)
require.NoError(t, err) require.NoError(t, err)

View File

@ -47,7 +47,7 @@ func TestMuteTimingService(t *testing.T) {
sut := createMuteTimingSvcSut() sut := createMuteTimingSvcSut()
sut.config.(*MockAMConfigStore).EXPECT(). sut.config.(*MockAMConfigStore).EXPECT().
GetLatestAlertmanagerConfiguration(mock.Anything, mock.Anything). GetLatestAlertmanagerConfiguration(mock.Anything, mock.Anything).
Return(fmt.Errorf("failed")) Return(nil, fmt.Errorf("failed"))
_, err := sut.GetMuteTimings(context.Background(), 1) _, err := sut.GetMuteTimings(context.Background(), 1)
@ -70,7 +70,7 @@ func TestMuteTimingService(t *testing.T) {
sut := createMuteTimingSvcSut() sut := createMuteTimingSvcSut()
sut.config.(*MockAMConfigStore).EXPECT(). sut.config.(*MockAMConfigStore).EXPECT().
GetLatestAlertmanagerConfiguration(mock.Anything, mock.Anything). GetLatestAlertmanagerConfiguration(mock.Anything, mock.Anything).
Return(nil) Return(nil, nil)
_, err := sut.GetMuteTimings(context.Background(), 1) _, err := sut.GetMuteTimings(context.Background(), 1)
@ -98,7 +98,7 @@ func TestMuteTimingService(t *testing.T) {
timing := createMuteTiming() timing := createMuteTiming()
sut.config.(*MockAMConfigStore).EXPECT(). sut.config.(*MockAMConfigStore).EXPECT().
GetLatestAlertmanagerConfiguration(mock.Anything, mock.Anything). GetLatestAlertmanagerConfiguration(mock.Anything, mock.Anything).
Return(fmt.Errorf("failed")) Return(nil, fmt.Errorf("failed"))
_, err := sut.CreateMuteTiming(context.Background(), timing, 1) _, err := sut.CreateMuteTiming(context.Background(), timing, 1)
@ -123,7 +123,7 @@ func TestMuteTimingService(t *testing.T) {
timing := createMuteTiming() timing := createMuteTiming()
sut.config.(*MockAMConfigStore).EXPECT(). sut.config.(*MockAMConfigStore).EXPECT().
GetLatestAlertmanagerConfiguration(mock.Anything, mock.Anything). GetLatestAlertmanagerConfiguration(mock.Anything, mock.Anything).
Return(nil) Return(nil, nil)
_, err := sut.CreateMuteTiming(context.Background(), timing, 1) _, err := sut.CreateMuteTiming(context.Background(), timing, 1)
@ -204,7 +204,7 @@ func TestMuteTimingService(t *testing.T) {
timing.Name = "asdf" timing.Name = "asdf"
sut.config.(*MockAMConfigStore).EXPECT(). sut.config.(*MockAMConfigStore).EXPECT().
GetLatestAlertmanagerConfiguration(mock.Anything, mock.Anything). GetLatestAlertmanagerConfiguration(mock.Anything, mock.Anything).
Return(fmt.Errorf("failed")) Return(nil, fmt.Errorf("failed"))
_, err := sut.UpdateMuteTiming(context.Background(), timing, 1) _, err := sut.UpdateMuteTiming(context.Background(), timing, 1)
@ -231,7 +231,7 @@ func TestMuteTimingService(t *testing.T) {
timing.Name = "asdf" timing.Name = "asdf"
sut.config.(*MockAMConfigStore).EXPECT(). sut.config.(*MockAMConfigStore).EXPECT().
GetLatestAlertmanagerConfiguration(mock.Anything, mock.Anything). GetLatestAlertmanagerConfiguration(mock.Anything, mock.Anything).
Return(nil) Return(nil, nil)
_, err := sut.UpdateMuteTiming(context.Background(), timing, 1) _, err := sut.UpdateMuteTiming(context.Background(), timing, 1)
@ -296,7 +296,7 @@ func TestMuteTimingService(t *testing.T) {
sut := createMuteTimingSvcSut() sut := createMuteTimingSvcSut()
sut.config.(*MockAMConfigStore).EXPECT(). sut.config.(*MockAMConfigStore).EXPECT().
GetLatestAlertmanagerConfiguration(mock.Anything, mock.Anything). GetLatestAlertmanagerConfiguration(mock.Anything, mock.Anything).
Return(fmt.Errorf("failed")) Return(nil, fmt.Errorf("failed"))
err := sut.DeleteMuteTiming(context.Background(), "asdf", 1) err := sut.DeleteMuteTiming(context.Background(), "asdf", 1)
@ -319,7 +319,7 @@ func TestMuteTimingService(t *testing.T) {
sut := createMuteTimingSvcSut() sut := createMuteTimingSvcSut()
sut.config.(*MockAMConfigStore).EXPECT(). sut.config.(*MockAMConfigStore).EXPECT().
GetLatestAlertmanagerConfiguration(mock.Anything, mock.Anything). GetLatestAlertmanagerConfiguration(mock.Anything, mock.Anything).
Return(nil) Return(nil, nil)
err := sut.DeleteMuteTiming(context.Background(), "asdf", 1) err := sut.DeleteMuteTiming(context.Background(), "asdf", 1)

View File

@ -37,12 +37,12 @@ func (nps *NotificationPolicyService) GetPolicyTree(ctx context.Context, orgID i
q := models.GetLatestAlertmanagerConfigurationQuery{ q := models.GetLatestAlertmanagerConfigurationQuery{
OrgID: orgID, OrgID: orgID,
} }
err := nps.amStore.GetLatestAlertmanagerConfiguration(ctx, &q) alertManagerConfig, err := nps.amStore.GetLatestAlertmanagerConfiguration(ctx, &q)
if err != nil { if err != nil {
return definitions.Route{}, err return definitions.Route{}, err
} }
cfg, err := deserializeAlertmanagerConfig([]byte(q.Result.AlertmanagerConfiguration)) cfg, err := deserializeAlertmanagerConfig([]byte(alertManagerConfig.AlertmanagerConfiguration))
if err != nil { if err != nil {
return definitions.Route{}, err return definitions.Route{}, err
} }

View File

@ -29,22 +29,16 @@ func TestNotificationPolicyService(t *testing.T) {
t.Run("error if referenced mute time interval is not existing", func(t *testing.T) { t.Run("error if referenced mute time interval is not existing", func(t *testing.T) {
sut := createNotificationPolicyServiceSut() sut := createNotificationPolicyServiceSut()
sut.amStore = &MockAMConfigStore{} sut.amStore = &MockAMConfigStore{}
cfg := createTestAlertingConfig()
cfg.AlertmanagerConfig.MuteTimeIntervals = []config.MuteTimeInterval{
{
Name: "not-the-one-we-need",
TimeIntervals: []timeinterval.TimeInterval{},
},
}
data, _ := serializeAlertmanagerConfig(*cfg)
sut.amStore.(*MockAMConfigStore).On("GetLatestAlertmanagerConfiguration", mock.Anything, mock.Anything). sut.amStore.(*MockAMConfigStore).On("GetLatestAlertmanagerConfiguration", mock.Anything, mock.Anything).
Return( Return(&models.AlertConfiguration{AlertmanagerConfiguration: string(data)}, nil)
func(ctx context.Context, query *models.GetLatestAlertmanagerConfigurationQuery) error {
cfg := createTestAlertingConfig()
cfg.AlertmanagerConfig.MuteTimeIntervals = []config.MuteTimeInterval{
{
Name: "not-the-one-we-need",
TimeIntervals: []timeinterval.TimeInterval{},
},
}
data, _ := serializeAlertmanagerConfig(*cfg)
query.Result = &models.AlertConfiguration{
AlertmanagerConfiguration: string(data),
}
return nil
})
sut.amStore.(*MockAMConfigStore).EXPECT(). sut.amStore.(*MockAMConfigStore).EXPECT().
UpdateAlertmanagerConfiguration(mock.Anything, mock.Anything). UpdateAlertmanagerConfiguration(mock.Anything, mock.Anything).
Return(nil) Return(nil)
@ -61,22 +55,16 @@ func TestNotificationPolicyService(t *testing.T) {
t.Run("pass if referenced mute time interval is existing", func(t *testing.T) { t.Run("pass if referenced mute time interval is existing", func(t *testing.T) {
sut := createNotificationPolicyServiceSut() sut := createNotificationPolicyServiceSut()
sut.amStore = &MockAMConfigStore{} sut.amStore = &MockAMConfigStore{}
cfg := createTestAlertingConfig()
cfg.AlertmanagerConfig.MuteTimeIntervals = []config.MuteTimeInterval{
{
Name: "existing",
TimeIntervals: []timeinterval.TimeInterval{},
},
}
data, _ := serializeAlertmanagerConfig(*cfg)
sut.amStore.(*MockAMConfigStore).On("GetLatestAlertmanagerConfiguration", mock.Anything, mock.Anything). sut.amStore.(*MockAMConfigStore).On("GetLatestAlertmanagerConfiguration", mock.Anything, mock.Anything).
Return( Return(&models.AlertConfiguration{AlertmanagerConfiguration: string(data)}, nil)
func(ctx context.Context, query *models.GetLatestAlertmanagerConfigurationQuery) error {
cfg := createTestAlertingConfig()
cfg.AlertmanagerConfig.MuteTimeIntervals = []config.MuteTimeInterval{
{
Name: "existing",
TimeIntervals: []timeinterval.TimeInterval{},
},
}
data, _ := serializeAlertmanagerConfig(*cfg)
query.Result = &models.AlertConfiguration{
AlertmanagerConfiguration: string(data),
}
return nil
})
sut.amStore.(*MockAMConfigStore).EXPECT(). sut.amStore.(*MockAMConfigStore).EXPECT().
UpdateAlertmanagerConfiguration(mock.Anything, mock.Anything). UpdateAlertmanagerConfiguration(mock.Anything, mock.Anything).
Return(nil) Return(nil)
@ -118,16 +106,10 @@ func TestNotificationPolicyService(t *testing.T) {
t.Run("existing receiver reference will pass", func(t *testing.T) { t.Run("existing receiver reference will pass", func(t *testing.T) {
sut := createNotificationPolicyServiceSut() sut := createNotificationPolicyServiceSut()
sut.amStore = &MockAMConfigStore{} sut.amStore = &MockAMConfigStore{}
cfg := createTestAlertingConfig()
data, _ := serializeAlertmanagerConfig(*cfg)
sut.amStore.(*MockAMConfigStore).On("GetLatestAlertmanagerConfiguration", mock.Anything, mock.Anything). sut.amStore.(*MockAMConfigStore).On("GetLatestAlertmanagerConfiguration", mock.Anything, mock.Anything).
Return( Return(&models.AlertConfiguration{AlertmanagerConfiguration: string(data)}, nil)
func(ctx context.Context, query *models.GetLatestAlertmanagerConfigurationQuery) error {
cfg := createTestAlertingConfig()
data, _ := serializeAlertmanagerConfig(*cfg)
query.Result = &models.AlertConfiguration{
AlertmanagerConfiguration: string(data),
}
return nil
})
sut.amStore.(*MockAMConfigStore).EXPECT(). sut.amStore.(*MockAMConfigStore).EXPECT().
UpdateAlertmanagerConfiguration(mock.Anything, mock.Anything). UpdateAlertmanagerConfiguration(mock.Anything, mock.Anything).
Return(nil) Return(nil)
@ -167,9 +149,9 @@ func TestNotificationPolicyService(t *testing.T) {
q := models.GetLatestAlertmanagerConfigurationQuery{ q := models.GetLatestAlertmanagerConfigurationQuery{
OrgID: 1, OrgID: 1,
} }
err := sut.GetAMConfigStore().GetLatestAlertmanagerConfiguration(context.Background(), &q) config, err := sut.GetAMConfigStore().GetLatestAlertmanagerConfiguration(context.Background(), &q)
require.NoError(t, err) require.NoError(t, err)
expectedConcurrencyToken := q.Result.ConfigurationHash expectedConcurrencyToken := config.ConfigurationHash
err = sut.UpdatePolicyTree(context.Background(), 1, newRoute, models.ProvenanceAPI) err = sut.UpdatePolicyTree(context.Background(), 1, newRoute, models.ProvenanceAPI)
require.NoError(t, err) require.NoError(t, err)
@ -205,27 +187,21 @@ func TestNotificationPolicyService(t *testing.T) {
t.Run("deleting route with missing default receiver restores receiver", func(t *testing.T) { t.Run("deleting route with missing default receiver restores receiver", func(t *testing.T) {
sut := createNotificationPolicyServiceSut() sut := createNotificationPolicyServiceSut()
sut.amStore = &MockAMConfigStore{} sut.amStore = &MockAMConfigStore{}
cfg := createTestAlertingConfig()
cfg.AlertmanagerConfig.Route = &definitions.Route{
Receiver: "a new receiver",
}
cfg.AlertmanagerConfig.Receivers = []*definitions.PostableApiReceiver{
{
Receiver: config.Receiver{
Name: "a new receiver",
},
},
// No default receiver! Only our custom one.
}
data, _ := serializeAlertmanagerConfig(*cfg)
sut.amStore.(*MockAMConfigStore).On("GetLatestAlertmanagerConfiguration", mock.Anything, mock.Anything). sut.amStore.(*MockAMConfigStore).On("GetLatestAlertmanagerConfiguration", mock.Anything, mock.Anything).
Return( Return(&models.AlertConfiguration{AlertmanagerConfiguration: string(data)}, nil)
func(ctx context.Context, query *models.GetLatestAlertmanagerConfigurationQuery) error {
cfg := createTestAlertingConfig()
cfg.AlertmanagerConfig.Route = &definitions.Route{
Receiver: "a new receiver",
}
cfg.AlertmanagerConfig.Receivers = []*definitions.PostableApiReceiver{
{
Receiver: config.Receiver{
Name: "a new receiver",
},
},
// No default receiver! Only our custom one.
}
data, _ := serializeAlertmanagerConfig(*cfg)
query.Result = &models.AlertConfiguration{
AlertmanagerConfiguration: string(data),
}
return nil
})
var interceptedSave = models.SaveAlertmanagerConfigurationCmd{} var interceptedSave = models.SaveAlertmanagerConfigurationCmd{}
sut.amStore.(*MockAMConfigStore).EXPECT().SaveSucceedsIntercept(&interceptedSave) sut.amStore.(*MockAMConfigStore).EXPECT().SaveSucceedsIntercept(&interceptedSave)

View File

@ -14,7 +14,7 @@ import (
// //
//go:generate mockery --name AMConfigStore --structname MockAMConfigStore --inpackage --filename persist_mock.go --with-expecter //go:generate mockery --name AMConfigStore --structname MockAMConfigStore --inpackage --filename persist_mock.go --with-expecter
type AMConfigStore interface { type AMConfigStore interface {
GetLatestAlertmanagerConfiguration(ctx context.Context, query *models.GetLatestAlertmanagerConfigurationQuery) error GetLatestAlertmanagerConfiguration(ctx context.Context, query *models.GetLatestAlertmanagerConfigurationQuery) (*models.AlertConfiguration, error)
UpdateAlertmanagerConfiguration(ctx context.Context, cmd *models.SaveAlertmanagerConfigurationCmd) error UpdateAlertmanagerConfiguration(ctx context.Context, cmd *models.SaveAlertmanagerConfigurationCmd) error
} }
@ -35,13 +35,13 @@ type TransactionManager interface {
// RuleStore represents the ability to persist and query alert rules. // RuleStore represents the ability to persist and query alert rules.
type RuleStore interface { type RuleStore interface {
GetAlertRuleByUID(ctx context.Context, query *models.GetAlertRuleByUIDQuery) error GetAlertRuleByUID(ctx context.Context, query *models.GetAlertRuleByUIDQuery) (*models.AlertRule, error)
ListAlertRules(ctx context.Context, query *models.ListAlertRulesQuery) error ListAlertRules(ctx context.Context, query *models.ListAlertRulesQuery) (models.RulesGroup, error)
GetRuleGroupInterval(ctx context.Context, orgID int64, namespaceUID string, ruleGroup string) (int64, error) GetRuleGroupInterval(ctx context.Context, orgID int64, namespaceUID string, ruleGroup string) (int64, error)
InsertAlertRules(ctx context.Context, rule []models.AlertRule) (map[string]int64, error) InsertAlertRules(ctx context.Context, rule []models.AlertRule) (map[string]int64, error)
UpdateAlertRules(ctx context.Context, rule []models.UpdateRule) error UpdateAlertRules(ctx context.Context, rule []models.UpdateRule) error
DeleteAlertRulesByUID(ctx context.Context, orgID int64, ruleUID ...string) error DeleteAlertRulesByUID(ctx context.Context, orgID int64, ruleUID ...string) error
GetAlertRulesGroupByRuleUID(ctx context.Context, query *models.GetAlertRulesGroupByRuleUIDQuery) error GetAlertRulesGroupByRuleUID(ctx context.Context, query *models.GetAlertRulesGroupByRuleUIDQuery) ([]*models.AlertRule, error)
} }
// QuotaChecker represents the ability to evaluate whether quotas are met. // QuotaChecker represents the ability to evaluate whether quotas are met.

View File

@ -1,14 +1,12 @@
// Code generated by mockery v2.12.0. DO NOT EDIT. // Code generated by mockery v2.16.0. DO NOT EDIT.
package provisioning package provisioning
import ( import (
context "context" context "context"
testing "testing"
mock "github.com/stretchr/testify/mock"
models "github.com/grafana/grafana/pkg/services/ngalert/models" models "github.com/grafana/grafana/pkg/services/ngalert/models"
mock "github.com/stretchr/testify/mock"
) )
// MockAMConfigStore is an autogenerated mock type for the AMConfigStore type // MockAMConfigStore is an autogenerated mock type for the AMConfigStore type
@ -25,17 +23,26 @@ func (_m *MockAMConfigStore) EXPECT() *MockAMConfigStore_Expecter {
} }
// GetLatestAlertmanagerConfiguration provides a mock function with given fields: ctx, query // GetLatestAlertmanagerConfiguration provides a mock function with given fields: ctx, query
func (_m *MockAMConfigStore) GetLatestAlertmanagerConfiguration(ctx context.Context, query *models.GetLatestAlertmanagerConfigurationQuery) error { func (_m *MockAMConfigStore) GetLatestAlertmanagerConfiguration(ctx context.Context, query *models.GetLatestAlertmanagerConfigurationQuery) (*models.AlertConfiguration, error) {
ret := _m.Called(ctx, query) ret := _m.Called(ctx, query)
var r0 error var r0 *models.AlertConfiguration
if rf, ok := ret.Get(0).(func(context.Context, *models.GetLatestAlertmanagerConfigurationQuery) error); ok { if rf, ok := ret.Get(0).(func(context.Context, *models.GetLatestAlertmanagerConfigurationQuery) *models.AlertConfiguration); ok {
r0 = rf(ctx, query) r0 = rf(ctx, query)
} else { } else {
r0 = ret.Error(0) if ret.Get(0) != nil {
r0 = ret.Get(0).(*models.AlertConfiguration)
}
} }
return r0 var r1 error
if rf, ok := ret.Get(1).(func(context.Context, *models.GetLatestAlertmanagerConfigurationQuery) error); ok {
r1 = rf(ctx, query)
} else {
r1 = ret.Error(1)
}
return r0, r1
} }
// MockAMConfigStore_GetLatestAlertmanagerConfiguration_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetLatestAlertmanagerConfiguration' // MockAMConfigStore_GetLatestAlertmanagerConfiguration_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetLatestAlertmanagerConfiguration'
@ -44,8 +51,8 @@ type MockAMConfigStore_GetLatestAlertmanagerConfiguration_Call struct {
} }
// GetLatestAlertmanagerConfiguration is a helper method to define mock.On call // GetLatestAlertmanagerConfiguration is a helper method to define mock.On call
// - ctx context.Context // - ctx context.Context
// - query *models.GetLatestAlertmanagerConfigurationQuery // - query *models.GetLatestAlertmanagerConfigurationQuery
func (_e *MockAMConfigStore_Expecter) GetLatestAlertmanagerConfiguration(ctx interface{}, query interface{}) *MockAMConfigStore_GetLatestAlertmanagerConfiguration_Call { func (_e *MockAMConfigStore_Expecter) GetLatestAlertmanagerConfiguration(ctx interface{}, query interface{}) *MockAMConfigStore_GetLatestAlertmanagerConfiguration_Call {
return &MockAMConfigStore_GetLatestAlertmanagerConfiguration_Call{Call: _e.mock.On("GetLatestAlertmanagerConfiguration", ctx, query)} return &MockAMConfigStore_GetLatestAlertmanagerConfiguration_Call{Call: _e.mock.On("GetLatestAlertmanagerConfiguration", ctx, query)}
} }
@ -57,8 +64,8 @@ func (_c *MockAMConfigStore_GetLatestAlertmanagerConfiguration_Call) Run(run fun
return _c return _c
} }
func (_c *MockAMConfigStore_GetLatestAlertmanagerConfiguration_Call) Return(_a0 error) *MockAMConfigStore_GetLatestAlertmanagerConfiguration_Call { func (_c *MockAMConfigStore_GetLatestAlertmanagerConfiguration_Call) Return(_a0 *models.AlertConfiguration, _a1 error) *MockAMConfigStore_GetLatestAlertmanagerConfiguration_Call {
_c.Call.Return(_a0) _c.Call.Return(_a0, _a1)
return _c return _c
} }
@ -82,8 +89,8 @@ type MockAMConfigStore_UpdateAlertmanagerConfiguration_Call struct {
} }
// UpdateAlertmanagerConfiguration is a helper method to define mock.On call // UpdateAlertmanagerConfiguration is a helper method to define mock.On call
// - ctx context.Context // - ctx context.Context
// - cmd *models.SaveAlertmanagerConfigurationCmd // - cmd *models.SaveAlertmanagerConfigurationCmd
func (_e *MockAMConfigStore_Expecter) UpdateAlertmanagerConfiguration(ctx interface{}, cmd interface{}) *MockAMConfigStore_UpdateAlertmanagerConfiguration_Call { func (_e *MockAMConfigStore_Expecter) UpdateAlertmanagerConfiguration(ctx interface{}, cmd interface{}) *MockAMConfigStore_UpdateAlertmanagerConfiguration_Call {
return &MockAMConfigStore_UpdateAlertmanagerConfiguration_Call{Call: _e.mock.On("UpdateAlertmanagerConfiguration", ctx, cmd)} return &MockAMConfigStore_UpdateAlertmanagerConfiguration_Call{Call: _e.mock.On("UpdateAlertmanagerConfiguration", ctx, cmd)}
} }
@ -100,8 +107,13 @@ func (_c *MockAMConfigStore_UpdateAlertmanagerConfiguration_Call) Return(_a0 err
return _c return _c
} }
// NewMockAMConfigStore creates a new instance of MockAMConfigStore. It also registers the testing.TB interface on the mock and a cleanup function to assert the mocks expectations. type mockConstructorTestingTNewMockAMConfigStore interface {
func NewMockAMConfigStore(t testing.TB) *MockAMConfigStore { mock.TestingT
Cleanup(func())
}
// NewMockAMConfigStore creates a new instance of MockAMConfigStore. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
func NewMockAMConfigStore(t mockConstructorTestingTNewMockAMConfigStore) *MockAMConfigStore {
mock := &MockAMConfigStore{} mock := &MockAMConfigStore{}
mock.Mock.Test(t) mock.Mock.Test(t)

View File

@ -46,7 +46,7 @@ func TestTemplateService(t *testing.T) {
sut := createTemplateServiceSut() sut := createTemplateServiceSut()
sut.config.(*MockAMConfigStore).EXPECT(). sut.config.(*MockAMConfigStore).EXPECT().
GetLatestAlertmanagerConfiguration(mock.Anything, mock.Anything). GetLatestAlertmanagerConfiguration(mock.Anything, mock.Anything).
Return(fmt.Errorf("failed")) Return(nil, fmt.Errorf("failed"))
_, err := sut.GetTemplates(context.Background(), 1) _, err := sut.GetTemplates(context.Background(), 1)
@ -69,7 +69,7 @@ func TestTemplateService(t *testing.T) {
sut := createTemplateServiceSut() sut := createTemplateServiceSut()
sut.config.(*MockAMConfigStore).EXPECT(). sut.config.(*MockAMConfigStore).EXPECT().
GetLatestAlertmanagerConfiguration(mock.Anything, mock.Anything). GetLatestAlertmanagerConfiguration(mock.Anything, mock.Anything).
Return(nil) Return(nil, nil)
_, err := sut.GetTemplates(context.Background(), 1) _, err := sut.GetTemplates(context.Background(), 1)
@ -96,7 +96,7 @@ func TestTemplateService(t *testing.T) {
tmpl := createNotificationTemplate() tmpl := createNotificationTemplate()
sut.config.(*MockAMConfigStore).EXPECT(). sut.config.(*MockAMConfigStore).EXPECT().
GetLatestAlertmanagerConfiguration(mock.Anything, mock.Anything). GetLatestAlertmanagerConfiguration(mock.Anything, mock.Anything).
Return(fmt.Errorf("failed")) Return(nil, fmt.Errorf("failed"))
_, err := sut.SetTemplate(context.Background(), 1, tmpl) _, err := sut.SetTemplate(context.Background(), 1, tmpl)
@ -121,7 +121,7 @@ func TestTemplateService(t *testing.T) {
tmpl := createNotificationTemplate() tmpl := createNotificationTemplate()
sut.config.(*MockAMConfigStore).EXPECT(). sut.config.(*MockAMConfigStore).EXPECT().
GetLatestAlertmanagerConfiguration(mock.Anything, mock.Anything). GetLatestAlertmanagerConfiguration(mock.Anything, mock.Anything).
Return(nil) Return(nil, nil)
_, err := sut.SetTemplate(context.Background(), 1, tmpl) _, err := sut.SetTemplate(context.Background(), 1, tmpl)
@ -273,7 +273,7 @@ func TestTemplateService(t *testing.T) {
sut := createTemplateServiceSut() sut := createTemplateServiceSut()
sut.config.(*MockAMConfigStore).EXPECT(). sut.config.(*MockAMConfigStore).EXPECT().
GetLatestAlertmanagerConfiguration(mock.Anything, mock.Anything). GetLatestAlertmanagerConfiguration(mock.Anything, mock.Anything).
Return(fmt.Errorf("failed")) Return(nil, fmt.Errorf("failed"))
err := sut.DeleteTemplate(context.Background(), 1, "template") err := sut.DeleteTemplate(context.Background(), 1, "template")
@ -296,7 +296,7 @@ func TestTemplateService(t *testing.T) {
sut := createTemplateServiceSut() sut := createTemplateServiceSut()
sut.config.(*MockAMConfigStore).EXPECT(). sut.config.(*MockAMConfigStore).EXPECT().
GetLatestAlertmanagerConfiguration(mock.Anything, mock.Anything). GetLatestAlertmanagerConfiguration(mock.Anything, mock.Anything).
Return(nil) Return(nil, nil)
err := sut.DeleteTemplate(context.Background(), 1, "template") err := sut.DeleteTemplate(context.Background(), 1, "template")

View File

@ -72,11 +72,11 @@ func newFakeAMConfigStore() *fakeAMConfigStore {
} }
} }
func (f *fakeAMConfigStore) GetLatestAlertmanagerConfiguration(ctx context.Context, query *models.GetLatestAlertmanagerConfigurationQuery) error { func (f *fakeAMConfigStore) GetLatestAlertmanagerConfiguration(ctx context.Context, query *models.GetLatestAlertmanagerConfigurationQuery) (*models.AlertConfiguration, error) {
query.Result = &f.config result := &f.config
query.Result.OrgID = query.OrgID result.OrgID = query.OrgID
query.Result.ConfigurationHash = fmt.Sprintf("%x", md5.Sum([]byte(f.config.AlertmanagerConfiguration))) result.ConfigurationHash = fmt.Sprintf("%x", md5.Sum([]byte(f.config.AlertmanagerConfiguration)))
return nil return result, nil
} }
func (f *fakeAMConfigStore) UpdateAlertmanagerConfiguration(ctx context.Context, cmd *models.SaveAlertmanagerConfigurationCmd) error { func (f *fakeAMConfigStore) UpdateAlertmanagerConfiguration(ctx context.Context, cmd *models.SaveAlertmanagerConfigurationCmd) error {
@ -148,11 +148,7 @@ func (n *NopTransactionManager) InTransaction(ctx context.Context, work func(ctx
} }
func (m *MockAMConfigStore_Expecter) GetsConfig(ac models.AlertConfiguration) *MockAMConfigStore_Expecter { func (m *MockAMConfigStore_Expecter) GetsConfig(ac models.AlertConfiguration) *MockAMConfigStore_Expecter {
m.GetLatestAlertmanagerConfiguration(mock.Anything, mock.Anything). m.GetLatestAlertmanagerConfiguration(mock.Anything, mock.Anything).Return(&ac, nil)
Run(func(ctx context.Context, q *models.GetLatestAlertmanagerConfigurationQuery) {
q.Result = &ac
}).
Return(nil)
return m return m
} }

View File

@ -34,7 +34,7 @@ type AnnotationBackend struct {
} }
type RuleStore interface { type RuleStore interface {
GetAlertRuleByUID(ctx context.Context, query *ngmodels.GetAlertRuleByUIDQuery) error GetAlertRuleByUID(ctx context.Context, query *ngmodels.GetAlertRuleByUIDQuery) (*ngmodels.AlertRule, error)
} }
type AnnotationStore interface { type AnnotationStore interface {
@ -89,16 +89,16 @@ func (h *AnnotationBackend) Query(ctx context.Context, query ngmodels.HistoryQue
UID: query.RuleUID, UID: query.RuleUID,
OrgID: query.OrgID, OrgID: query.OrgID,
} }
err := h.rules.GetAlertRuleByUID(ctx, &rq) rule, err := h.rules.GetAlertRuleByUID(ctx, &rq)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to look up the requested rule") return nil, fmt.Errorf("failed to look up the requested rule")
} }
if rq.Result == nil { if rule == nil {
return nil, fmt.Errorf("no such rule exists") return nil, fmt.Errorf("no such rule exists")
} }
q := annotations.ItemQuery{ q := annotations.ItemQuery{
AlertID: rq.Result.ID, AlertID: rule.ID,
OrgID: query.OrgID, OrgID: query.OrgID,
From: query.From.Unix(), From: query.From.Unix(),
To: query.To.Unix(), To: query.To.Unix(),

View File

@ -103,12 +103,13 @@ func (st *Manager) Warm(ctx context.Context, rulesReader RuleReader) {
ruleCmd := ngModels.ListAlertRulesQuery{ ruleCmd := ngModels.ListAlertRulesQuery{
OrgID: orgId, OrgID: orgId,
} }
if err := rulesReader.ListAlertRules(ctx, &ruleCmd); err != nil { alertRules, err := rulesReader.ListAlertRules(ctx, &ruleCmd)
if err != nil {
st.log.Error("Unable to fetch previous state", "error", err) st.log.Error("Unable to fetch previous state", "error", err)
} }
ruleByUID := make(map[string]*ngModels.AlertRule, len(ruleCmd.Result)) ruleByUID := make(map[string]*ngModels.AlertRule, len(alertRules))
for _, rule := range ruleCmd.Result { for _, rule := range alertRules {
ruleByUID[rule.UID] = rule ruleByUID[rule.UID] = rule
} }
@ -119,11 +120,12 @@ func (st *Manager) Warm(ctx context.Context, rulesReader RuleReader) {
cmd := ngModels.ListAlertInstancesQuery{ cmd := ngModels.ListAlertInstancesQuery{
RuleOrgID: orgId, RuleOrgID: orgId,
} }
if err := st.instanceStore.ListAlertInstances(ctx, &cmd); err != nil { alertInstances, err := st.instanceStore.ListAlertInstances(ctx, &cmd)
if err != nil {
st.log.Error("Unable to fetch previous state", "error", err) st.log.Error("Unable to fetch previous state", "error", err)
} }
for _, entry := range cmd.Result { for _, entry := range alertInstances {
ruleForEntry, ok := ruleByUID[entry.RuleUID] ruleForEntry, ok := ruleByUID[entry.RuleUID]
if !ok { if !ok {
// TODO Should we delete the orphaned state from the db? // TODO Should we delete the orphaned state from the db?

View File

@ -2639,12 +2639,12 @@ func TestDeleteStateByRuleUID(t *testing.T) {
st := state.NewManager(cfg) st := state.NewManager(cfg)
st.Warm(ctx, dbstore) st.Warm(ctx, dbstore)
q := &models.ListAlertInstancesQuery{RuleOrgID: rule.OrgID, RuleUID: rule.UID} q := &models.ListAlertInstancesQuery{RuleOrgID: rule.OrgID, RuleUID: rule.UID}
_ = dbstore.ListAlertInstances(ctx, q) alerts, _ := dbstore.ListAlertInstances(ctx, q)
existingStatesForRule := st.GetStatesForRuleUID(rule.OrgID, rule.UID) existingStatesForRule := st.GetStatesForRuleUID(rule.OrgID, rule.UID)
// We have loaded the expected number of entries from the db // We have loaded the expected number of entries from the db
assert.Equal(t, tc.startingStateCacheCount, len(existingStatesForRule)) assert.Equal(t, tc.startingStateCacheCount, len(existingStatesForRule))
assert.Equal(t, tc.startingInstanceDBCount, len(q.Result)) assert.Equal(t, tc.startingInstanceDBCount, len(alerts))
expectedReason := util.GenerateShortUID() expectedReason := util.GenerateShortUID()
transitions := st.DeleteStateByRuleUID(ctx, rule.GetKey(), expectedReason) transitions := st.DeleteStateByRuleUID(ctx, rule.GetKey(), expectedReason)
@ -2671,12 +2671,12 @@ func TestDeleteStateByRuleUID(t *testing.T) {
} }
q = &models.ListAlertInstancesQuery{RuleOrgID: rule.OrgID, RuleUID: rule.UID} q = &models.ListAlertInstancesQuery{RuleOrgID: rule.OrgID, RuleUID: rule.UID}
_ = dbstore.ListAlertInstances(ctx, q) alertInstances, _ := dbstore.ListAlertInstances(ctx, q)
existingStatesForRule = st.GetStatesForRuleUID(rule.OrgID, rule.UID) existingStatesForRule = st.GetStatesForRuleUID(rule.OrgID, rule.UID)
// The expected number of state entries remains after states are deleted // The expected number of state entries remains after states are deleted
assert.Equal(t, tc.finalStateCacheCount, len(existingStatesForRule)) assert.Equal(t, tc.finalStateCacheCount, len(existingStatesForRule))
assert.Equal(t, tc.finalInstanceDBCount, len(q.Result)) assert.Equal(t, tc.finalInstanceDBCount, len(alertInstances))
}) })
} }
} }
@ -2776,12 +2776,12 @@ func TestResetStateByRuleUID(t *testing.T) {
st := state.NewManager(cfg) st := state.NewManager(cfg)
st.Warm(ctx, dbstore) st.Warm(ctx, dbstore)
q := &models.ListAlertInstancesQuery{RuleOrgID: rule.OrgID, RuleUID: rule.UID} q := &models.ListAlertInstancesQuery{RuleOrgID: rule.OrgID, RuleUID: rule.UID}
_ = dbstore.ListAlertInstances(ctx, q) alerts, _ := dbstore.ListAlertInstances(ctx, q)
existingStatesForRule := st.GetStatesForRuleUID(rule.OrgID, rule.UID) existingStatesForRule := st.GetStatesForRuleUID(rule.OrgID, rule.UID)
// We have loaded the expected number of entries from the db // We have loaded the expected number of entries from the db
assert.Equal(t, tc.startingStateCacheCount, len(existingStatesForRule)) assert.Equal(t, tc.startingStateCacheCount, len(existingStatesForRule))
assert.Equal(t, tc.startingInstanceDBCount, len(q.Result)) assert.Equal(t, tc.startingInstanceDBCount, len(alerts))
transitions := st.ResetStateByRuleUID(ctx, rule, models.StateReasonPaused) transitions := st.ResetStateByRuleUID(ctx, rule, models.StateReasonPaused)
@ -2811,12 +2811,12 @@ func TestResetStateByRuleUID(t *testing.T) {
assert.Equal(t, transitions, fakeHistorian.StateTransitions) assert.Equal(t, transitions, fakeHistorian.StateTransitions)
q = &models.ListAlertInstancesQuery{RuleOrgID: rule.OrgID, RuleUID: rule.UID} q = &models.ListAlertInstancesQuery{RuleOrgID: rule.OrgID, RuleUID: rule.UID}
_ = dbstore.ListAlertInstances(ctx, q) alertInstances, _ := dbstore.ListAlertInstances(ctx, q)
existingStatesForRule = st.GetStatesForRuleUID(rule.OrgID, rule.UID) existingStatesForRule = st.GetStatesForRuleUID(rule.OrgID, rule.UID)
// The expected number of state entries remains after states are deleted // The expected number of state entries remains after states are deleted
assert.Equal(t, tc.finalStateCacheCount, len(existingStatesForRule)) assert.Equal(t, tc.finalStateCacheCount, len(existingStatesForRule))
assert.Equal(t, tc.finalInstanceDBCount, len(q.Result)) assert.Equal(t, tc.finalInstanceDBCount, len(alertInstances))
}) })
} }
} }

View File

@ -10,7 +10,7 @@ import (
// InstanceStore represents the ability to fetch and write alert instances. // InstanceStore represents the ability to fetch and write alert instances.
type InstanceStore interface { type InstanceStore interface {
FetchOrgIds(ctx context.Context) ([]int64, error) FetchOrgIds(ctx context.Context) ([]int64, error)
ListAlertInstances(ctx context.Context, cmd *models.ListAlertInstancesQuery) error ListAlertInstances(ctx context.Context, cmd *models.ListAlertInstancesQuery) ([]*models.AlertInstance, error)
SaveAlertInstances(ctx context.Context, cmd ...models.AlertInstance) error SaveAlertInstances(ctx context.Context, cmd ...models.AlertInstance) error
DeleteAlertInstances(ctx context.Context, keys ...models.AlertInstanceKey) error DeleteAlertInstances(ctx context.Context, keys ...models.AlertInstanceKey) error
DeleteAlertInstancesByRule(ctx context.Context, key models.AlertRuleKey) error DeleteAlertInstancesByRule(ctx context.Context, key models.AlertRuleKey) error
@ -18,7 +18,7 @@ type InstanceStore interface {
// RuleReader represents the ability to fetch alert rules. // RuleReader represents the ability to fetch alert rules.
type RuleReader interface { type RuleReader interface {
ListAlertRules(ctx context.Context, query *models.ListAlertRulesQuery) error ListAlertRules(ctx context.Context, query *models.ListAlertRulesQuery) (models.RulesGroup, error)
} }
// Historian maintains an audit log of alert state history. // Historian maintains an audit log of alert state history.

View File

@ -21,11 +21,11 @@ type FakeInstanceStoreOp struct {
Args []interface{} Args []interface{}
} }
func (f *FakeInstanceStore) ListAlertInstances(_ context.Context, q *models.ListAlertInstancesQuery) error { func (f *FakeInstanceStore) ListAlertInstances(_ context.Context, q *models.ListAlertInstancesQuery) ([]*models.AlertInstance, error) {
f.mtx.Lock() f.mtx.Lock()
defer f.mtx.Unlock() defer f.mtx.Unlock()
f.RecordedOps = append(f.RecordedOps, *q) f.RecordedOps = append(f.RecordedOps, *q)
return nil return nil, nil
} }
func (f *FakeInstanceStore) SaveAlertInstances(_ context.Context, q ...models.AlertInstance) error { func (f *FakeInstanceStore) SaveAlertInstances(_ context.Context, q ...models.AlertInstance) error {
@ -57,8 +57,8 @@ func (f *FakeInstanceStore) DeleteAlertInstancesByRule(ctx context.Context, key
type FakeRuleReader struct{} type FakeRuleReader struct{}
func (f *FakeRuleReader) ListAlertRules(_ context.Context, q *models.ListAlertRulesQuery) error { func (f *FakeRuleReader) ListAlertRules(_ context.Context, q *models.ListAlertRulesQuery) (models.RulesGroup, error) {
return nil return nil, nil
} }
type FakeHistorian struct { type FakeHistorian struct {

View File

@ -83,31 +83,33 @@ func (st DBstore) IncreaseVersionForAllRulesInNamespace(ctx context.Context, org
// GetAlertRuleByUID is a handler for retrieving an alert rule from that database by its UID and organisation ID. // GetAlertRuleByUID is a handler for retrieving an alert rule from that database by its UID and organisation ID.
// It returns ngmodels.ErrAlertRuleNotFound if no alert rule is found for the provided ID. // It returns ngmodels.ErrAlertRuleNotFound if no alert rule is found for the provided ID.
func (st DBstore) GetAlertRuleByUID(ctx context.Context, query *ngmodels.GetAlertRuleByUIDQuery) error { func (st DBstore) GetAlertRuleByUID(ctx context.Context, query *ngmodels.GetAlertRuleByUIDQuery) (result *ngmodels.AlertRule, err error) {
return st.SQLStore.WithDbSession(ctx, func(sess *db.Session) error { err = st.SQLStore.WithDbSession(ctx, func(sess *db.Session) error {
alertRule, err := getAlertRuleByUID(sess, query.UID, query.OrgID) alertRule, err := getAlertRuleByUID(sess, query.UID, query.OrgID)
if err != nil { if err != nil {
return err return err
} }
query.Result = alertRule result = alertRule
return nil return nil
}) })
return result, err
} }
// GetAlertRulesGroupByRuleUID is a handler for retrieving a group of alert rules from that database by UID and organisation ID of one of rules that belong to that group. // GetAlertRulesGroupByRuleUID is a handler for retrieving a group of alert rules from that database by UID and organisation ID of one of rules that belong to that group.
func (st DBstore) GetAlertRulesGroupByRuleUID(ctx context.Context, query *ngmodels.GetAlertRulesGroupByRuleUIDQuery) error { func (st DBstore) GetAlertRulesGroupByRuleUID(ctx context.Context, query *ngmodels.GetAlertRulesGroupByRuleUIDQuery) (result []*ngmodels.AlertRule, err error) {
return st.SQLStore.WithDbSession(ctx, func(sess *db.Session) error { err = st.SQLStore.WithDbSession(ctx, func(sess *db.Session) error {
var result []*ngmodels.AlertRule var rules []*ngmodels.AlertRule
err := sess.Table("alert_rule").Alias("a").Join( err := sess.Table("alert_rule").Alias("a").Join(
"INNER", "INNER",
"alert_rule AS b", "a.org_id = b.org_id AND a.namespace_uid = b.namespace_uid AND a.rule_group = b.rule_group AND b.uid = ?", query.UID, "alert_rule AS b", "a.org_id = b.org_id AND a.namespace_uid = b.namespace_uid AND a.rule_group = b.rule_group AND b.uid = ?", query.UID,
).Where("a.org_id = ?", query.OrgID).Select("a.*").Find(&result) ).Where("a.org_id = ?", query.OrgID).Select("a.*").Find(&rules)
if err != nil { if err != nil {
return err return err
} }
query.Result = result result = rules
return nil return nil
}) })
return result, err
} }
// InsertAlertRules is a handler for creating/updating alert rules. // InsertAlertRules is a handler for creating/updating alert rules.
@ -243,8 +245,8 @@ func (st DBstore) CountAlertRulesInFolder(ctx context.Context, query *ngmodels.C
} }
// ListAlertRules is a handler for retrieving alert rules of specific organisation. // ListAlertRules is a handler for retrieving alert rules of specific organisation.
func (st DBstore) ListAlertRules(ctx context.Context, query *ngmodels.ListAlertRulesQuery) error { func (st DBstore) ListAlertRules(ctx context.Context, query *ngmodels.ListAlertRulesQuery) (result ngmodels.RulesGroup, err error) {
return st.SQLStore.WithDbSession(ctx, func(sess *db.Session) error { err = st.SQLStore.WithDbSession(ctx, func(sess *db.Session) error {
q := sess.Table("alert_rule") q := sess.Table("alert_rule")
if query.OrgID >= 0 { if query.OrgID >= 0 {
@ -295,9 +297,10 @@ func (st DBstore) ListAlertRules(ctx context.Context, query *ngmodels.ListAlertR
alertRules = append(alertRules, rule) alertRules = append(alertRules, rule)
} }
query.Result = alertRules result = alertRules
return nil return nil
}) })
return result, err
} }
// Count returns either the number of the alert rules under a specific org (if orgID is not zero) // Count returns either the number of the alert rules under a specific org (if orgID is not zero)

View File

@ -24,8 +24,8 @@ var (
// GetLatestAlertmanagerConfiguration returns the lastest version of the alertmanager configuration. // GetLatestAlertmanagerConfiguration returns the lastest version of the alertmanager configuration.
// It returns ErrNoAlertmanagerConfiguration if no configuration is found. // It returns ErrNoAlertmanagerConfiguration if no configuration is found.
func (st *DBstore) GetLatestAlertmanagerConfiguration(ctx context.Context, query *models.GetLatestAlertmanagerConfigurationQuery) error { func (st *DBstore) GetLatestAlertmanagerConfiguration(ctx context.Context, query *models.GetLatestAlertmanagerConfigurationQuery) (result *models.AlertConfiguration, err error) {
return st.SQLStore.WithDbSession(ctx, func(sess *db.Session) error { err = st.SQLStore.WithDbSession(ctx, func(sess *db.Session) error {
c := &models.AlertConfiguration{} c := &models.AlertConfiguration{}
// The ID is already an auto incremental column, using the ID as an order should guarantee the latest. // The ID is already an auto incremental column, using the ID as an order should guarantee the latest.
ok, err := sess.Table("alert_configuration").Where("org_id = ?", query.OrgID).Get(c) ok, err := sess.Table("alert_configuration").Where("org_id = ?", query.OrgID).Get(c)
@ -37,9 +37,10 @@ func (st *DBstore) GetLatestAlertmanagerConfiguration(ctx context.Context, query
return ErrNoAlertmanagerConfiguration return ErrNoAlertmanagerConfiguration
} }
query.Result = c result = c
return nil return nil
}) })
return result, err
} }
// GetAllLatestAlertmanagerConfiguration returns the latest configuration of every organization // GetAllLatestAlertmanagerConfiguration returns the latest configuration of every organization
@ -162,8 +163,8 @@ func (st *DBstore) MarkConfigurationAsApplied(ctx context.Context, cmd *models.M
} }
// GetAppliedConfigurations returns all configurations that have been marked as applied, ordered newest -> oldest by id. // GetAppliedConfigurations returns all configurations that have been marked as applied, ordered newest -> oldest by id.
func (st *DBstore) GetAppliedConfigurations(ctx context.Context, query *models.GetAppliedConfigurationsQuery) error { func (st *DBstore) GetAppliedConfigurations(ctx context.Context, query *models.GetAppliedConfigurationsQuery) (result []*models.HistoricAlertConfiguration, err error) {
return st.SQLStore.WithDbSession(ctx, func(sess *db.Session) error { err = st.SQLStore.WithDbSession(ctx, func(sess *db.Session) error {
cfgs := []*models.HistoricAlertConfiguration{} cfgs := []*models.HistoricAlertConfiguration{}
err := sess.Table("alert_configuration_history"). err := sess.Table("alert_configuration_history").
Desc("id"). Desc("id").
@ -174,9 +175,10 @@ func (st *DBstore) GetAppliedConfigurations(ctx context.Context, query *models.G
return err return err
} }
query.Result = cfgs result = cfgs
return nil return nil
}) })
return result, err
} }
func (st *DBstore) deleteOldConfigurations(ctx context.Context, orgID int64, limit int) (int64, error) { func (st *DBstore) deleteOldConfigurations(ctx context.Context, orgID int64, limit int) (int64, error) {

View File

@ -30,10 +30,10 @@ func TestIntegrationAlertmanagerStore(t *testing.T) {
OrgID: 1234, OrgID: 1234,
} }
err := store.GetLatestAlertmanagerConfiguration(context.Background(), req) config, err := store.GetLatestAlertmanagerConfiguration(context.Background(), req)
require.ErrorIs(t, err, ErrNoAlertmanagerConfiguration) require.ErrorIs(t, err, ErrNoAlertmanagerConfiguration)
require.Nil(t, req.Result) require.Nil(t, config)
}) })
t.Run("GetLatestAlertmanagerConfiguration return the right config", func(t *testing.T) { t.Run("GetLatestAlertmanagerConfiguration return the right config", func(t *testing.T) {
@ -42,12 +42,12 @@ func TestIntegrationAlertmanagerStore(t *testing.T) {
OrgID: 1, OrgID: 1,
} }
err := store.GetLatestAlertmanagerConfiguration(context.Background(), req) config, err := store.GetLatestAlertmanagerConfiguration(context.Background(), req)
require.NoError(t, err) require.NoError(t, err)
require.NotNil(t, req.Result) require.NotNil(t, config)
require.Equal(t, "my-config", req.Result.AlertmanagerConfiguration) require.Equal(t, "my-config", config.AlertmanagerConfiguration)
require.Equal(t, configMD5, req.Result.ConfigurationHash) require.Equal(t, configMD5, config.ConfigurationHash)
}) })
t.Run("GetLatestAlertmanagerConfiguration after saving multiple times should return the latest config", func(t *testing.T) { t.Run("GetLatestAlertmanagerConfiguration after saving multiple times should return the latest config", func(t *testing.T) {
@ -58,12 +58,12 @@ func TestIntegrationAlertmanagerStore(t *testing.T) {
OrgID: 1, OrgID: 1,
} }
err := store.GetLatestAlertmanagerConfiguration(context.Background(), req) config, err := store.GetLatestAlertmanagerConfiguration(context.Background(), req)
require.NoError(t, err) require.NoError(t, err)
require.NotNil(t, req.Result) require.NotNil(t, config)
require.Equal(t, "my-config3", req.Result.AlertmanagerConfiguration) require.Equal(t, "my-config3", config.AlertmanagerConfiguration)
require.Equal(t, configMD5, req.Result.ConfigurationHash) require.Equal(t, configMD5, config.ConfigurationHash)
}) })
t.Run("GetAllLatestAlertmanagerConfiguration gets latest config for all orgs", func(t *testing.T) { t.Run("GetAllLatestAlertmanagerConfiguration gets latest config for all orgs", func(t *testing.T) {
@ -109,9 +109,9 @@ func TestIntegrationAlertmanagerStore(t *testing.T) {
require.ErrorContains(t, err, "callback failed") require.ErrorContains(t, err, "callback failed")
// Assert that we rolled back the transaction. // Assert that we rolled back the transaction.
get := &models.GetLatestAlertmanagerConfigurationQuery{OrgID: 1} get := &models.GetLatestAlertmanagerConfigurationQuery{OrgID: 1}
err = store.GetLatestAlertmanagerConfiguration(context.Background(), get) config, err := store.GetLatestAlertmanagerConfiguration(context.Background(), get)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, get.Result.AlertmanagerConfiguration, "my-config") require.Equal(t, config.AlertmanagerConfiguration, "my-config")
}) })
t.Run("UpdateAlertmanagerConfiguration returns error if existing config does not exist", func(t *testing.T) { t.Run("UpdateAlertmanagerConfiguration returns error if existing config does not exist", func(t *testing.T) {
@ -138,9 +138,9 @@ func TestIntegrationAlertmanagerHash(t *testing.T) {
req := &models.GetLatestAlertmanagerConfigurationQuery{ req := &models.GetLatestAlertmanagerConfigurationQuery{
OrgID: 1, OrgID: 1,
} }
err := store.GetLatestAlertmanagerConfiguration(context.Background(), req) config, err := store.GetLatestAlertmanagerConfiguration(context.Background(), req)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, configMD5, req.Result.ConfigurationHash) require.Equal(t, configMD5, config.ConfigurationHash)
newConfig, newConfigMD5 := "my-config-new", fmt.Sprintf("%x", md5.Sum([]byte("my-config-new"))) newConfig, newConfigMD5 := "my-config-new", fmt.Sprintf("%x", md5.Sum([]byte("my-config-new")))
err = store.UpdateAlertmanagerConfiguration(context.Background(), &models.SaveAlertmanagerConfigurationCmd{ err = store.UpdateAlertmanagerConfiguration(context.Background(), &models.SaveAlertmanagerConfigurationCmd{
AlertmanagerConfiguration: newConfig, AlertmanagerConfiguration: newConfig,
@ -150,10 +150,10 @@ func TestIntegrationAlertmanagerHash(t *testing.T) {
OrgID: 1, OrgID: 1,
}) })
require.NoError(t, err) require.NoError(t, err)
err = store.GetLatestAlertmanagerConfiguration(context.Background(), req) config, err = store.GetLatestAlertmanagerConfiguration(context.Background(), req)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, newConfig, req.Result.AlertmanagerConfiguration) require.Equal(t, newConfig, config.AlertmanagerConfiguration)
require.Equal(t, newConfigMD5, req.Result.ConfigurationHash) require.Equal(t, newConfigMD5, config.ConfigurationHash)
}) })
t.Run("When passing the wrong hash the update should error", func(t *testing.T) { t.Run("When passing the wrong hash the update should error", func(t *testing.T) {
@ -161,9 +161,9 @@ func TestIntegrationAlertmanagerHash(t *testing.T) {
req := &models.GetLatestAlertmanagerConfigurationQuery{ req := &models.GetLatestAlertmanagerConfigurationQuery{
OrgID: 1, OrgID: 1,
} }
err := store.GetLatestAlertmanagerConfiguration(context.Background(), req) amConfig, err := store.GetLatestAlertmanagerConfiguration(context.Background(), req)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, configMD5, req.Result.ConfigurationHash) require.Equal(t, configMD5, amConfig.ConfigurationHash)
err = store.UpdateAlertmanagerConfiguration(context.Background(), &models.SaveAlertmanagerConfigurationCmd{ err = store.UpdateAlertmanagerConfiguration(context.Background(), &models.SaveAlertmanagerConfigurationCmd{
AlertmanagerConfiguration: config, AlertmanagerConfiguration: config,
FetchedConfigurationHash: "the-wrong-hash", FetchedConfigurationHash: "the-wrong-hash",
@ -221,9 +221,9 @@ func TestIntegrationAlertmanagerConfigCleanup(t *testing.T) {
req := &models.GetLatestAlertmanagerConfigurationQuery{ req := &models.GetLatestAlertmanagerConfigurationQuery{
OrgID: orgID, OrgID: orgID,
} }
err = store.GetLatestAlertmanagerConfiguration(context.Background(), req) amConfig, err := store.GetLatestAlertmanagerConfiguration(context.Background(), req)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, "newest-record", req.Result.AlertmanagerConfiguration) require.Equal(t, "newest-record", amConfig.AlertmanagerConfiguration)
}) })
t.Run("when calling the cleanup only the oldest records surpassing the limit should be deleted", func(t *testing.T) { t.Run("when calling the cleanup only the oldest records surpassing the limit should be deleted", func(t *testing.T) {
var orgID int64 = 2 var orgID int64 = 2
@ -261,9 +261,9 @@ func TestIntegrationAlertmanagerConfigCleanup(t *testing.T) {
req := &models.GetLatestAlertmanagerConfigurationQuery{ req := &models.GetLatestAlertmanagerConfigurationQuery{
OrgID: orgID, OrgID: orgID,
} }
err = store.GetLatestAlertmanagerConfiguration(context.Background(), req) amConfig, err := store.GetLatestAlertmanagerConfiguration(context.Background(), req)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, "newest-record", req.Result.AlertmanagerConfiguration) require.Equal(t, "newest-record", amConfig.AlertmanagerConfiguration)
}) })
t.Run("limit set to 0 should fail", func(t *testing.T) { t.Run("limit set to 0 should fail", func(t *testing.T) {
_, err := store.deleteOldConfigurations(context.Background(), 1, 0) _, err := store.deleteOldConfigurations(context.Background(), 1, 0)
@ -311,19 +311,19 @@ func TestIntegrationMarkConfigurationAsApplied(t *testing.T) {
appliedCfgsQuery := models.GetAppliedConfigurationsQuery{ appliedCfgsQuery := models.GetAppliedConfigurationsQuery{
OrgID: orgID, OrgID: orgID,
} }
err = store.GetAppliedConfigurations(ctx, &appliedCfgsQuery) configs, err := store.GetAppliedConfigurations(ctx, &appliedCfgsQuery)
require.NoError(tt, err) require.NoError(tt, err)
require.Len(tt, appliedCfgsQuery.Result, 0) require.Len(tt, configs, 0)
query := models.GetLatestAlertmanagerConfigurationQuery{ query := models.GetLatestAlertmanagerConfigurationQuery{
OrgID: orgID, OrgID: orgID,
} }
err = store.GetLatestAlertmanagerConfiguration(ctx, &query) amConfig, err := store.GetLatestAlertmanagerConfiguration(ctx, &query)
require.NoError(tt, err) require.NoError(tt, err)
cmd := models.MarkConfigurationAsAppliedCmd{ cmd := models.MarkConfigurationAsAppliedCmd{
OrgID: orgID, OrgID: orgID,
ConfigurationHash: query.Result.ConfigurationHash, ConfigurationHash: amConfig.ConfigurationHash,
} }
err = store.MarkConfigurationAsApplied(ctx, &cmd) err = store.MarkConfigurationAsApplied(ctx, &cmd)
require.NoError(tt, err) require.NoError(tt, err)
@ -332,9 +332,9 @@ func TestIntegrationMarkConfigurationAsApplied(t *testing.T) {
appliedCfgsQuery = models.GetAppliedConfigurationsQuery{ appliedCfgsQuery = models.GetAppliedConfigurationsQuery{
OrgID: orgID, OrgID: orgID,
} }
err = store.GetAppliedConfigurations(ctx, &appliedCfgsQuery) configs, err = store.GetAppliedConfigurations(ctx, &appliedCfgsQuery)
require.NoError(tt, err) require.NoError(tt, err)
require.Len(tt, appliedCfgsQuery.Result, 1) require.Len(tt, configs, 1)
}) })
} }

View File

@ -22,7 +22,7 @@ const AlertDefinitionMaxTitleLength = 190
// AlertingStore is the database interface used by the Alertmanager service. // AlertingStore is the database interface used by the Alertmanager service.
type AlertingStore interface { type AlertingStore interface {
GetLatestAlertmanagerConfiguration(ctx context.Context, query *models.GetLatestAlertmanagerConfigurationQuery) error GetLatestAlertmanagerConfiguration(ctx context.Context, query *models.GetLatestAlertmanagerConfigurationQuery) (*models.AlertConfiguration, error)
GetAllLatestAlertmanagerConfiguration(ctx context.Context) ([]*models.AlertConfiguration, error) GetAllLatestAlertmanagerConfiguration(ctx context.Context) ([]*models.AlertConfiguration, error)
SaveAlertmanagerConfiguration(ctx context.Context, cmd *models.SaveAlertmanagerConfigurationCmd) error SaveAlertmanagerConfiguration(ctx context.Context, cmd *models.SaveAlertmanagerConfigurationCmd) error
SaveAlertmanagerConfigurationWithCallback(ctx context.Context, cmd *models.SaveAlertmanagerConfigurationCmd, callback SaveCallback) error SaveAlertmanagerConfigurationWithCallback(ctx context.Context, cmd *models.SaveAlertmanagerConfigurationCmd, callback SaveCallback) error

View File

@ -32,8 +32,8 @@ func (c *GroupDelta) IsEmpty() bool {
} }
type RuleReader interface { type RuleReader interface {
ListAlertRules(ctx context.Context, query *models.ListAlertRulesQuery) error ListAlertRules(ctx context.Context, query *models.ListAlertRulesQuery) (models.RulesGroup, error)
GetAlertRulesGroupByRuleUID(ctx context.Context, query *models.GetAlertRulesGroupByRuleUIDQuery) error GetAlertRulesGroupByRuleUID(ctx context.Context, query *models.GetAlertRulesGroupByRuleUIDQuery) ([]*models.AlertRule, error)
} }
// CalculateChanges calculates the difference between rules in the group in the database and the submitted rules. If a submitted rule has UID it tries to find it in the database (in other groups). // CalculateChanges calculates the difference between rules in the group in the database and the submitted rules. If a submitted rule has UID it tries to find it in the database (in other groups).
@ -45,10 +45,10 @@ func CalculateChanges(ctx context.Context, ruleReader RuleReader, groupKey model
NamespaceUIDs: []string{groupKey.NamespaceUID}, NamespaceUIDs: []string{groupKey.NamespaceUID},
RuleGroup: groupKey.RuleGroup, RuleGroup: groupKey.RuleGroup,
} }
if err := ruleReader.ListAlertRules(ctx, q); err != nil { existingGroupRules, err := ruleReader.ListAlertRules(ctx, q)
if err != nil {
return nil, fmt.Errorf("failed to query database for rules in the group %s: %w", groupKey, err) return nil, fmt.Errorf("failed to query database for rules in the group %s: %w", groupKey, err)
} }
existingGroupRules := q.Result
if len(existingGroupRules) > 0 { if len(existingGroupRules) > 0 {
affectedGroups[groupKey] = existingGroupRules affectedGroups[groupKey] = existingGroupRules
} }
@ -76,10 +76,11 @@ func CalculateChanges(ctx context.Context, ruleReader RuleReader, groupKey model
} else if existing, ok = loadedRulesByUID[r.UID]; !ok { // check the "cache" and if there is no hit, query the database } else if existing, ok = loadedRulesByUID[r.UID]; !ok { // check the "cache" and if there is no hit, query the database
// Rule can be from other group or namespace // Rule can be from other group or namespace
q := &models.GetAlertRulesGroupByRuleUIDQuery{OrgID: groupKey.OrgID, UID: r.UID} q := &models.GetAlertRulesGroupByRuleUIDQuery{OrgID: groupKey.OrgID, UID: r.UID}
if err := ruleReader.GetAlertRulesGroupByRuleUID(ctx, q); err != nil { ruleList, err := ruleReader.GetAlertRulesGroupByRuleUID(ctx, q)
if err != nil {
return nil, fmt.Errorf("failed to query database for a group of alert rules: %w", err) return nil, fmt.Errorf("failed to query database for a group of alert rules: %w", err)
} }
for _, rule := range q.Result { for _, rule := range ruleList {
if rule.UID == r.UID { if rule.UID == r.UID {
existing = rule existing = rule
} }
@ -88,7 +89,7 @@ func CalculateChanges(ctx context.Context, ruleReader RuleReader, groupKey model
if existing == nil { if existing == nil {
return nil, fmt.Errorf("failed to update rule with UID %s because %w", r.UID, models.ErrAlertRuleNotFound) return nil, fmt.Errorf("failed to update rule with UID %s because %w", r.UID, models.ErrAlertRuleNotFound)
} }
affectedGroups[existing.GetGroupKey()] = q.Result affectedGroups[existing.GetGroupKey()] = ruleList
} }
} }

View File

@ -13,8 +13,8 @@ import (
// ListAlertInstances is a handler for retrieving alert instances within specific organisation // ListAlertInstances is a handler for retrieving alert instances within specific organisation
// based on various filters. // based on various filters.
func (st DBstore) ListAlertInstances(ctx context.Context, cmd *models.ListAlertInstancesQuery) error { func (st DBstore) ListAlertInstances(ctx context.Context, cmd *models.ListAlertInstancesQuery) (result []*models.AlertInstance, err error) {
return st.SQLStore.WithDbSession(ctx, func(sess *db.Session) error { err = st.SQLStore.WithDbSession(ctx, func(sess *db.Session) error {
alertInstances := make([]*models.AlertInstance, 0) alertInstances := make([]*models.AlertInstance, 0)
s := strings.Builder{} s := strings.Builder{}
@ -37,9 +37,10 @@ func (st DBstore) ListAlertInstances(ctx context.Context, cmd *models.ListAlertI
return err return err
} }
cmd.Result = alertInstances result = alertInstances
return nil return nil
}) })
return result, err
} }
// SaveAlertInstances saves all the provided alert instances to the store. // SaveAlertInstances saves all the provided alert instances to the store.

View File

@ -99,9 +99,9 @@ func TestIntegrationAlertInstanceBulkWrite(t *testing.T) {
q := &models.ListAlertInstancesQuery{ q := &models.ListAlertInstancesQuery{
RuleOrgID: id, RuleOrgID: id,
} }
err = dbstore.ListAlertInstances(ctx, q) alerts, err := dbstore.ListAlertInstances(ctx, q)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, counts[i], len(q.Result), "Org %v: Expected %v instances but got %v", id, counts[i], len(q.Result)) require.Equal(t, counts[i], len(alerts), "Org %v: Expected %v instances but got %v", id, counts[i], len(alerts))
} }
t.Log("Finished database read") t.Log("Finished database read")
@ -113,9 +113,9 @@ func TestIntegrationAlertInstanceBulkWrite(t *testing.T) {
q := &models.ListAlertInstancesQuery{ q := &models.ListAlertInstancesQuery{
RuleOrgID: id, RuleOrgID: id,
} }
err = dbstore.ListAlertInstances(ctx, q) alerts, err := dbstore.ListAlertInstances(ctx, q)
require.NoError(t, err) require.NoError(t, err)
require.Zero(t, len(q.Result), "Org %v: Deleted instances but still had %v", id, len(q.Result)) require.Zero(t, len(alerts), "Org %v: Deleted instances but still had %v", id, len(alerts))
} }
} }
} }
@ -171,14 +171,14 @@ func TestIntegrationAlertInstanceOperations(t *testing.T) {
RuleOrgID: instance.RuleOrgID, RuleOrgID: instance.RuleOrgID,
RuleUID: instance.RuleUID, RuleUID: instance.RuleUID,
} }
err = dbstore.ListAlertInstances(ctx, listCmd) alerts, err := dbstore.ListAlertInstances(ctx, listCmd)
require.NoError(t, err) require.NoError(t, err)
require.Len(t, listCmd.Result, 1) require.Len(t, alerts, 1)
require.Equal(t, instance.Labels, listCmd.Result[0].Labels) require.Equal(t, instance.Labels, alerts[0].Labels)
require.Equal(t, alertRule1.OrgID, listCmd.Result[0].RuleOrgID) require.Equal(t, alertRule1.OrgID, alerts[0].RuleOrgID)
require.Equal(t, alertRule1.UID, listCmd.Result[0].RuleUID) require.Equal(t, alertRule1.UID, alerts[0].RuleUID)
require.Equal(t, instance.CurrentReason, listCmd.Result[0].CurrentReason) require.Equal(t, instance.CurrentReason, alerts[0].CurrentReason)
}) })
t.Run("can save and read new alert instance with no labels", func(t *testing.T) { t.Run("can save and read new alert instance with no labels", func(t *testing.T) {
@ -201,13 +201,13 @@ func TestIntegrationAlertInstanceOperations(t *testing.T) {
RuleUID: instance.RuleUID, RuleUID: instance.RuleUID,
} }
err = dbstore.ListAlertInstances(ctx, listCmd) alerts, err := dbstore.ListAlertInstances(ctx, listCmd)
require.NoError(t, err) require.NoError(t, err)
require.Len(t, listCmd.Result, 1) require.Len(t, alerts, 1)
require.Equal(t, alertRule2.OrgID, listCmd.Result[0].RuleOrgID) require.Equal(t, alertRule2.OrgID, alerts[0].RuleOrgID)
require.Equal(t, alertRule2.UID, listCmd.Result[0].RuleUID) require.Equal(t, alertRule2.UID, alerts[0].RuleUID)
require.Equal(t, instance.Labels, listCmd.Result[0].Labels) require.Equal(t, instance.Labels, alerts[0].Labels)
}) })
t.Run("can save two instances with same org_id, uid and different labels", func(t *testing.T) { t.Run("can save two instances with same org_id, uid and different labels", func(t *testing.T) {
@ -245,10 +245,10 @@ func TestIntegrationAlertInstanceOperations(t *testing.T) {
RuleUID: instance1.RuleUID, RuleUID: instance1.RuleUID,
} }
err = dbstore.ListAlertInstances(ctx, listQuery) alerts, err := dbstore.ListAlertInstances(ctx, listQuery)
require.NoError(t, err) require.NoError(t, err)
require.Len(t, listQuery.Result, 2) require.Len(t, alerts, 2)
}) })
t.Run("can list all added instances in org", func(t *testing.T) { t.Run("can list all added instances in org", func(t *testing.T) {
@ -256,10 +256,10 @@ func TestIntegrationAlertInstanceOperations(t *testing.T) {
RuleOrgID: orgID, RuleOrgID: orgID,
} }
err := dbstore.ListAlertInstances(ctx, listQuery) alerts, err := dbstore.ListAlertInstances(ctx, listQuery)
require.NoError(t, err) require.NoError(t, err)
require.Len(t, listQuery.Result, 4) require.Len(t, alerts, 4)
}) })
t.Run("should ignore Normal state with no reason if feature flag is enabled", func(t *testing.T) { t.Run("should ignore Normal state with no reason if feature flag is enabled", func(t *testing.T) {
@ -291,10 +291,10 @@ func TestIntegrationAlertInstanceOperations(t *testing.T) {
RuleOrgID: orgID, RuleOrgID: orgID,
} }
err = dbstore.ListAlertInstances(ctx, listQuery) alerts, err := dbstore.ListAlertInstances(ctx, listQuery)
require.NoError(t, err) require.NoError(t, err)
containsHash(t, listQuery.Result, instance1.LabelsHash) containsHash(t, alerts, instance1.LabelsHash)
f := dbstore.FeatureToggles f := dbstore.FeatureToggles
dbstore.FeatureToggles = featuremgmt.WithFeatures(featuremgmt.FlagAlertingNoNormalState) dbstore.FeatureToggles = featuremgmt.WithFeatures(featuremgmt.FlagAlertingNoNormalState)
@ -302,12 +302,12 @@ func TestIntegrationAlertInstanceOperations(t *testing.T) {
dbstore.FeatureToggles = f dbstore.FeatureToggles = f
}) })
err = dbstore.ListAlertInstances(ctx, listQuery) alerts, err = dbstore.ListAlertInstances(ctx, listQuery)
require.NoError(t, err) require.NoError(t, err)
containsHash(t, listQuery.Result, instance2.LabelsHash) containsHash(t, alerts, instance2.LabelsHash)
for _, instance := range listQuery.Result { for _, instance := range alerts {
if instance.CurrentState == models.InstanceStateNormal && instance.CurrentReason == "" { if instance.CurrentState == models.InstanceStateNormal && instance.CurrentReason == "" {
require.Fail(t, "List operation expected to return all states except Normal but the result contains Normal states") require.Fail(t, "List operation expected to return all states except Normal but the result contains Normal states")
} }
@ -347,14 +347,14 @@ func TestIntegrationAlertInstanceOperations(t *testing.T) {
RuleUID: alertRule4.UID, RuleUID: alertRule4.UID,
} }
err = dbstore.ListAlertInstances(ctx, listQuery) alerts, err := dbstore.ListAlertInstances(ctx, listQuery)
require.NoError(t, err) require.NoError(t, err)
require.Len(t, listQuery.Result, 1) require.Len(t, alerts, 1)
require.Equal(t, instance2.RuleOrgID, listQuery.Result[0].RuleOrgID) require.Equal(t, instance2.RuleOrgID, alerts[0].RuleOrgID)
require.Equal(t, instance2.RuleUID, listQuery.Result[0].RuleUID) require.Equal(t, instance2.RuleUID, alerts[0].RuleUID)
require.Equal(t, instance2.Labels, listQuery.Result[0].Labels) require.Equal(t, instance2.Labels, alerts[0].Labels)
require.Equal(t, instance2.CurrentState, listQuery.Result[0].CurrentState) require.Equal(t, instance2.CurrentState, alerts[0].CurrentState)
}) })
} }

View File

@ -120,37 +120,36 @@ func (f *RuleStore) DeleteAlertRulesByUID(_ context.Context, orgID int64, UIDs .
return nil return nil
} }
func (f *RuleStore) GetAlertRuleByUID(_ context.Context, q *models.GetAlertRuleByUIDQuery) error { func (f *RuleStore) GetAlertRuleByUID(_ context.Context, q *models.GetAlertRuleByUIDQuery) (*models.AlertRule, error) {
f.mtx.Lock() f.mtx.Lock()
defer f.mtx.Unlock() defer f.mtx.Unlock()
f.RecordedOps = append(f.RecordedOps, *q) f.RecordedOps = append(f.RecordedOps, *q)
if err := f.Hook(*q); err != nil { if err := f.Hook(*q); err != nil {
return err return nil, err
} }
rules, ok := f.Rules[q.OrgID] rules, ok := f.Rules[q.OrgID]
if !ok { if !ok {
return nil return nil, nil
} }
for _, rule := range rules { for _, rule := range rules {
if rule.UID == q.UID { if rule.UID == q.UID {
q.Result = rule return rule, nil
break
} }
} }
return nil return nil, nil
} }
func (f *RuleStore) GetAlertRulesGroupByRuleUID(_ context.Context, q *models.GetAlertRulesGroupByRuleUIDQuery) error { func (f *RuleStore) GetAlertRulesGroupByRuleUID(_ context.Context, q *models.GetAlertRulesGroupByRuleUIDQuery) ([]*models.AlertRule, error) {
f.mtx.Lock() f.mtx.Lock()
defer f.mtx.Unlock() defer f.mtx.Unlock()
f.RecordedOps = append(f.RecordedOps, *q) f.RecordedOps = append(f.RecordedOps, *q)
if err := f.Hook(*q); err != nil { if err := f.Hook(*q); err != nil {
return err return nil, err
} }
rules, ok := f.Rules[q.OrgID] rules, ok := f.Rules[q.OrgID]
if !ok { if !ok {
return nil return nil, nil
} }
var selected *models.AlertRule var selected *models.AlertRule
@ -161,24 +160,25 @@ func (f *RuleStore) GetAlertRulesGroupByRuleUID(_ context.Context, q *models.Get
} }
} }
if selected == nil { if selected == nil {
return nil return nil, nil
} }
ruleList := []*models.AlertRule{}
for _, rule := range rules { for _, rule := range rules {
if rule.GetGroupKey() == selected.GetGroupKey() { if rule.GetGroupKey() == selected.GetGroupKey() {
q.Result = append(q.Result, rule) ruleList = append(ruleList, rule)
} }
} }
return nil return ruleList, nil
} }
func (f *RuleStore) ListAlertRules(_ context.Context, q *models.ListAlertRulesQuery) error { func (f *RuleStore) ListAlertRules(_ context.Context, q *models.ListAlertRulesQuery) (models.RulesGroup, error) {
f.mtx.Lock() f.mtx.Lock()
defer f.mtx.Unlock() defer f.mtx.Unlock()
f.RecordedOps = append(f.RecordedOps, *q) f.RecordedOps = append(f.RecordedOps, *q)
if err := f.Hook(*q); err != nil { if err := f.Hook(*q); err != nil {
return err return nil, err
} }
hasDashboard := func(r *models.AlertRule, dashboardUID string, panelID int64) bool { hasDashboard := func(r *models.AlertRule, dashboardUID string, panelID int64) bool {
@ -211,6 +211,7 @@ func (f *RuleStore) ListAlertRules(_ context.Context, q *models.ListAlertRulesQu
return true return true
} }
ruleList := models.RulesGroup{}
for _, r := range f.Rules[q.OrgID] { for _, r := range f.Rules[q.OrgID] {
if !hasDashboard(r, q.DashboardUID, q.PanelID) { if !hasDashboard(r, q.DashboardUID, q.PanelID) {
continue continue
@ -221,10 +222,10 @@ func (f *RuleStore) ListAlertRules(_ context.Context, q *models.ListAlertRulesQu
if q.RuleGroup != "" && r.RuleGroup != q.RuleGroup { if q.RuleGroup != "" && r.RuleGroup != q.RuleGroup {
continue continue
} }
q.Result = append(q.Result, r) ruleList = append(ruleList, r)
} }
return nil return ruleList, nil
} }
func (f *RuleStore) GetUserVisibleNamespaces(_ context.Context, orgID int64, _ *user.SignedInUser) (map[string]*folder.Folder, error) { func (f *RuleStore) GetUserVisibleNamespaces(_ context.Context, orgID int64, _ *user.SignedInUser) (map[string]*folder.Folder, error) {

View File

@ -168,11 +168,11 @@ func CreateTestAlertRuleWithLabels(t testing.TB, ctx context.Context, dbstore *s
NamespaceUIDs: []string{folderUID}, NamespaceUIDs: []string{folderUID},
RuleGroup: ruleGroup, RuleGroup: ruleGroup,
} }
err = dbstore.ListAlertRules(ctx, &q) ruleList, err := dbstore.ListAlertRules(ctx, &q)
require.NoError(t, err) require.NoError(t, err)
require.NotEmpty(t, q.Result) require.NotEmpty(t, ruleList)
rule := q.Result[0] rule := ruleList[0]
t.Logf("alert definition: %v with title: %q interval: %d folder: %s created", rule.GetKey(), rule.Title, rule.IntervalSeconds, folderUID) t.Logf("alert definition: %v with title: %q interval: %d folder: %s created", rule.GetKey(), rule.Title, rule.IntervalSeconds, folderUID)
return rule return rule
} }