Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
N
nexpie-grafana-theme
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Registry
Registry
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kornkitt Poolsup
nexpie-grafana-theme
Commits
f132e929
Commit
f132e929
authored
Dec 14, 2018
by
Pavel Bakulev
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added uid for alert notifications
parent
6d1ec19f
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
26 changed files
with
381 additions
and
234 deletions
+381
-234
conf/provisioning/alert_notifications/sample.yaml
+9
-7
docs/sources/administration/provisioning.md
+4
-2
pkg/models/alert_notifications.go
+30
-2
pkg/services/alerting/interfaces.go
+1
-1
pkg/services/alerting/notifier.go
+6
-6
pkg/services/alerting/notifiers/base.go
+4
-4
pkg/services/alerting/notifiers/base_test.go
+1
-1
pkg/services/alerting/rule.go
+3
-16
pkg/services/alerting/rule_test.go
+2
-157
pkg/services/alerting/testdata/dash-without-id.json
+1
-1
pkg/services/alerting/testdata/influxdb-alert.json
+1
-1
pkg/services/provisioning/alert_notifications/alert_notifications.go
+19
-7
pkg/services/provisioning/alert_notifications/config_reader.go
+45
-2
pkg/services/provisioning/alert_notifications/config_reader_test.go
+0
-0
pkg/services/provisioning/alert_notifications/test-configs/correct-properties-with-orgName/correct-properties-with-orgName.yaml
+5
-13
pkg/services/provisioning/alert_notifications/test-configs/correct-properties/correct-properties.yaml
+10
-0
pkg/services/provisioning/alert_notifications/test-configs/double-default/default-1.yml
+2
-0
pkg/services/provisioning/alert_notifications/test-configs/double-default/default-2.yaml
+2
-0
pkg/services/provisioning/alert_notifications/test-configs/incorrect-settings/incorrect-settings.yaml
+1
-0
pkg/services/provisioning/alert_notifications/test-configs/no-required-fields/no-required-fields.yaml
+36
-0
pkg/services/provisioning/alert_notifications/test-configs/two-notifications/two-notifications.yaml
+7
-4
pkg/services/provisioning/alert_notifications/test-configs/unknown-notifier/notification.yaml
+2
-0
pkg/services/provisioning/alert_notifications/types.go
+5
-0
pkg/services/sqlstore/alert_notification.go
+141
-7
pkg/services/sqlstore/alert_notification_test.go
+30
-3
pkg/services/sqlstore/migrations/alert_mig.go
+14
-0
No files found.
conf/provisioning/alert_notifications/sample.yaml
View file @
f132e929
...
@@ -2,10 +2,11 @@
...
@@ -2,10 +2,11 @@
apiVersion
:
1
apiVersion
:
1
# alert_notifications:
# alert_notifications:
# - name: default-slack
# - name: default-slack
-temp
# type: slack
# type: slack
# org_
id: 1
# org_
name: Main Org.
# is_default: true
# is_default: true
# uid: notifier1
# settings:
# settings:
# recipient: "XXX"
# recipient: "XXX"
# token: "xoxb"
# token: "xoxb"
...
@@ -14,10 +15,11 @@ apiVersion: 1
...
@@ -14,10 +15,11 @@ apiVersion: 1
# - name: default-email
# - name: default-email
# type: email
# type: email
# org_id: 1
# org_id: 1
# uid: notifier2
# is_default: false
# is_default: false
# settings:
# settings:
# addresses: example@example.com
# addresses: example
11111
@example.com
# delete_alert_notifications:
# delete_alert_notifications:
# - name: default-slack
# - name: default-slack-temp
# org_id: 1
# org_name: Main Org.
# - name: default-email
# uid: notifier1
\ No newline at end of file
\ No newline at end of file
docs/sources/administration/provisioning.md
View file @
f132e929
...
@@ -253,8 +253,8 @@ By default, exporting a dashboard as JSON will use a sequential identifier to re
...
@@ -253,8 +253,8 @@ By default, exporting a dashboard as JSON will use a sequential identifier to re
"frequency"
:
"24h"
,
"frequency"
:
"24h"
,
"noDataState"
:
"ok"
,
"noDataState"
:
"ok"
,
"notifications"
:
[
"notifications"
:
[
{
"
name"
:
"notification-channel-
1"
},
{
"
uid"
:
"notifier
1"
},
{
"
name"
:
"notification-channel-
2"
},
{
"
uid"
:
"notifier
2"
},
]
]
}
}
...
...
...
@@ -267,6 +267,7 @@ By default, exporting a dashboard as JSON will use a sequential identifier to re
...
@@ -267,6 +267,7 @@ By default, exporting a dashboard as JSON will use a sequential identifier to re
alert_notifications
:
alert_notifications
:
-
name
:
notification-channel-1
-
name
:
notification-channel-1
type
:
slack
type
:
slack
uid
:
notifier1
# either
# either
org_id
:
2
org_id
:
2
# or
# or
...
@@ -282,6 +283,7 @@ alert_notifications:
...
@@ -282,6 +283,7 @@ alert_notifications:
delete_alert_notifications
:
delete_alert_notifications
:
-
name
:
notification-channel-1
-
name
:
notification-channel-1
uid
:
notifier1
# either
# either
org_id
:
2
org_id
:
2
# or
# or
...
...
pkg/models/alert_notifications.go
View file @
f132e929
...
@@ -12,6 +12,7 @@ var (
...
@@ -12,6 +12,7 @@ var (
ErrAlertNotificationStateNotFound
=
errors
.
New
(
"alert notification state not found"
)
ErrAlertNotificationStateNotFound
=
errors
.
New
(
"alert notification state not found"
)
ErrAlertNotificationStateVersionConflict
=
errors
.
New
(
"alert notification state update version conflict"
)
ErrAlertNotificationStateVersionConflict
=
errors
.
New
(
"alert notification state update version conflict"
)
ErrAlertNotificationStateAlreadyExist
=
errors
.
New
(
"alert notification state already exists."
)
ErrAlertNotificationStateAlreadyExist
=
errors
.
New
(
"alert notification state already exists."
)
ErrAlertNotificationFailedGenerateUniqueUid
=
errors
.
New
(
"Failed to generate unique alert notification uid"
)
)
)
type
AlertNotificationStateType
string
type
AlertNotificationStateType
string
...
@@ -24,6 +25,7 @@ var (
...
@@ -24,6 +25,7 @@ var (
type
AlertNotification
struct
{
type
AlertNotification
struct
{
Id
int64
`json:"id"`
Id
int64
`json:"id"`
Uid
string
`json:"-"`
OrgId
int64
`json:"-"`
OrgId
int64
`json:"-"`
Name
string
`json:"name"`
Name
string
`json:"name"`
Type
string
`json:"type"`
Type
string
`json:"type"`
...
@@ -37,6 +39,7 @@ type AlertNotification struct {
...
@@ -37,6 +39,7 @@ type AlertNotification struct {
}
}
type
CreateAlertNotificationCommand
struct
{
type
CreateAlertNotificationCommand
struct
{
Uid
string
`json:"-"`
Name
string
`json:"name" binding:"Required"`
Name
string
`json:"name" binding:"Required"`
Type
string
`json:"type" binding:"Required"`
Type
string
`json:"type" binding:"Required"`
SendReminder
bool
`json:"sendReminder"`
SendReminder
bool
`json:"sendReminder"`
...
@@ -63,10 +66,28 @@ type UpdateAlertNotificationCommand struct {
...
@@ -63,10 +66,28 @@ type UpdateAlertNotificationCommand struct {
Result
*
AlertNotification
Result
*
AlertNotification
}
}
type
UpdateAlertNotificationWithUidCommand
struct
{
Uid
string
Name
string
Type
string
SendReminder
bool
DisableResolveMessage
bool
Frequency
string
IsDefault
bool
Settings
*
simplejson
.
Json
OrgId
int64
Result
*
AlertNotification
}
type
DeleteAlertNotificationCommand
struct
{
type
DeleteAlertNotificationCommand
struct
{
Id
int64
Id
int64
OrgId
int64
OrgId
int64
}
}
type
DeleteAlertNotificationWithUidCommand
struct
{
Uid
string
OrgId
int64
}
type
GetAlertNotificationsQuery
struct
{
type
GetAlertNotificationsQuery
struct
{
Name
string
Name
string
...
@@ -76,8 +97,15 @@ type GetAlertNotificationsQuery struct {
...
@@ -76,8 +97,15 @@ type GetAlertNotificationsQuery struct {
Result
*
AlertNotification
Result
*
AlertNotification
}
}
type
GetAlertNotificationsToSendQuery
struct
{
type
GetAlertNotificationsWithUidQuery
struct
{
Ids
[]
int64
Uid
string
OrgId
int64
Result
*
AlertNotification
}
type
GetAlertNotificationsWithUidToSendQuery
struct
{
Uids
[]
string
OrgId
int64
OrgId
int64
Result
[]
*
AlertNotification
Result
[]
*
AlertNotification
...
...
pkg/services/alerting/interfaces.go
View file @
f132e929
...
@@ -24,7 +24,7 @@ type Notifier interface {
...
@@ -24,7 +24,7 @@ type Notifier interface {
// ShouldNotify checks this evaluation should send an alert notification
// ShouldNotify checks this evaluation should send an alert notification
ShouldNotify
(
ctx
context
.
Context
,
evalContext
*
EvalContext
,
notificationState
*
models
.
AlertNotificationState
)
bool
ShouldNotify
(
ctx
context
.
Context
,
evalContext
*
EvalContext
,
notificationState
*
models
.
AlertNotificationState
)
bool
GetNotifier
Id
()
int64
GetNotifier
Uid
()
string
GetIsDefault
()
bool
GetIsDefault
()
bool
GetSendReminder
()
bool
GetSendReminder
()
bool
GetDisableResolveMessage
()
bool
GetDisableResolveMessage
()
bool
...
...
pkg/services/alerting/notifier.go
View file @
f132e929
...
@@ -60,13 +60,13 @@ func (n *notificationService) SendIfNeeded(context *EvalContext) error {
...
@@ -60,13 +60,13 @@ func (n *notificationService) SendIfNeeded(context *EvalContext) error {
func
(
n
*
notificationService
)
sendAndMarkAsComplete
(
evalContext
*
EvalContext
,
notifierState
*
notifierState
)
error
{
func
(
n
*
notificationService
)
sendAndMarkAsComplete
(
evalContext
*
EvalContext
,
notifierState
*
notifierState
)
error
{
notifier
:=
notifierState
.
notifier
notifier
:=
notifierState
.
notifier
n
.
log
.
Debug
(
"Sending notification"
,
"type"
,
notifier
.
GetType
(),
"
id"
,
notifier
.
GetNotifierI
d
(),
"isDefault"
,
notifier
.
GetIsDefault
())
n
.
log
.
Debug
(
"Sending notification"
,
"type"
,
notifier
.
GetType
(),
"
uid"
,
notifier
.
GetNotifierUi
d
(),
"isDefault"
,
notifier
.
GetIsDefault
())
metrics
.
M_Alerting_Notification_Sent
.
WithLabelValues
(
notifier
.
GetType
())
.
Inc
()
metrics
.
M_Alerting_Notification_Sent
.
WithLabelValues
(
notifier
.
GetType
())
.
Inc
()
err
:=
notifier
.
Notify
(
evalContext
)
err
:=
notifier
.
Notify
(
evalContext
)
if
err
!=
nil
{
if
err
!=
nil
{
n
.
log
.
Error
(
"failed to send notification"
,
"
id"
,
notifier
.
GetNotifierI
d
(),
"error"
,
err
)
n
.
log
.
Error
(
"failed to send notification"
,
"
uid"
,
notifier
.
GetNotifierUi
d
(),
"error"
,
err
)
}
}
if
evalContext
.
IsTestRun
{
if
evalContext
.
IsTestRun
{
...
@@ -110,7 +110,7 @@ func (n *notificationService) sendNotifications(evalContext *EvalContext, notifi
...
@@ -110,7 +110,7 @@ func (n *notificationService) sendNotifications(evalContext *EvalContext, notifi
for
_
,
notifierState
:=
range
notifierStates
{
for
_
,
notifierState
:=
range
notifierStates
{
err
:=
n
.
sendNotification
(
evalContext
,
notifierState
)
err
:=
n
.
sendNotification
(
evalContext
,
notifierState
)
if
err
!=
nil
{
if
err
!=
nil
{
n
.
log
.
Error
(
"failed to send notification"
,
"
id"
,
notifierState
.
notifier
.
GetNotifierI
d
(),
"error"
,
err
)
n
.
log
.
Error
(
"failed to send notification"
,
"
uid"
,
notifierState
.
notifier
.
GetNotifierUi
d
(),
"error"
,
err
)
}
}
}
}
...
@@ -157,8 +157,8 @@ func (n *notificationService) uploadImage(context *EvalContext) (err error) {
...
@@ -157,8 +157,8 @@ func (n *notificationService) uploadImage(context *EvalContext) (err error) {
return
nil
return
nil
}
}
func
(
n
*
notificationService
)
getNeededNotifiers
(
orgId
int64
,
notification
Ids
[]
int64
,
evalContext
*
EvalContext
)
(
notifierStateSlice
,
error
)
{
func
(
n
*
notificationService
)
getNeededNotifiers
(
orgId
int64
,
notification
Uids
[]
string
,
evalContext
*
EvalContext
)
(
notifierStateSlice
,
error
)
{
query
:=
&
m
.
GetAlertNotifications
ToSendQuery
{
OrgId
:
orgId
,
Ids
:
notificationI
ds
}
query
:=
&
m
.
GetAlertNotifications
WithUidToSendQuery
{
OrgId
:
orgId
,
Uids
:
notificationUi
ds
}
if
err
:=
bus
.
Dispatch
(
query
);
err
!=
nil
{
if
err
:=
bus
.
Dispatch
(
query
);
err
!=
nil
{
return
nil
,
err
return
nil
,
err
...
@@ -168,7 +168,7 @@ func (n *notificationService) getNeededNotifiers(orgId int64, notificationIds []
...
@@ -168,7 +168,7 @@ func (n *notificationService) getNeededNotifiers(orgId int64, notificationIds []
for
_
,
notification
:=
range
query
.
Result
{
for
_
,
notification
:=
range
query
.
Result
{
not
,
err
:=
InitNotifier
(
notification
)
not
,
err
:=
InitNotifier
(
notification
)
if
err
!=
nil
{
if
err
!=
nil
{
n
.
log
.
Error
(
"Could not create notifier"
,
"notifier"
,
notification
.
I
d
,
"error"
,
err
)
n
.
log
.
Error
(
"Could not create notifier"
,
"notifier"
,
notification
.
Ui
d
,
"error"
,
err
)
continue
continue
}
}
...
...
pkg/services/alerting/notifiers/base.go
View file @
f132e929
...
@@ -16,7 +16,7 @@ const (
...
@@ -16,7 +16,7 @@ const (
type
NotifierBase
struct
{
type
NotifierBase
struct
{
Name
string
Name
string
Type
string
Type
string
Id
int64
Uid
string
IsDeault
bool
IsDeault
bool
UploadImage
bool
UploadImage
bool
SendReminder
bool
SendReminder
bool
...
@@ -34,7 +34,7 @@ func NewNotifierBase(model *models.AlertNotification) NotifierBase {
...
@@ -34,7 +34,7 @@ func NewNotifierBase(model *models.AlertNotification) NotifierBase {
}
}
return
NotifierBase
{
return
NotifierBase
{
Id
:
model
.
I
d
,
Uid
:
model
.
Ui
d
,
Name
:
model
.
Name
,
Name
:
model
.
Name
,
IsDeault
:
model
.
IsDefault
,
IsDeault
:
model
.
IsDefault
,
Type
:
model
.
Type
,
Type
:
model
.
Type
,
...
@@ -110,8 +110,8 @@ func (n *NotifierBase) NeedsImage() bool {
...
@@ -110,8 +110,8 @@ func (n *NotifierBase) NeedsImage() bool {
return
n
.
UploadImage
return
n
.
UploadImage
}
}
func
(
n
*
NotifierBase
)
GetNotifier
Id
()
int64
{
func
(
n
*
NotifierBase
)
GetNotifier
Uid
()
string
{
return
n
.
I
d
return
n
.
Ui
d
}
}
func
(
n
*
NotifierBase
)
GetIsDefault
()
bool
{
func
(
n
*
NotifierBase
)
GetIsDefault
()
bool
{
...
...
pkg/services/alerting/notifiers/base_test.go
View file @
f132e929
...
@@ -173,7 +173,7 @@ func TestBaseNotifier(t *testing.T) {
...
@@ -173,7 +173,7 @@ func TestBaseNotifier(t *testing.T) {
bJson
:=
simplejson
.
New
()
bJson
:=
simplejson
.
New
()
model
:=
&
m
.
AlertNotification
{
model
:=
&
m
.
AlertNotification
{
Id
:
1
,
Uid
:
"1"
,
Name
:
"name"
,
Name
:
"name"
,
Type
:
"email"
,
Type
:
"email"
,
Settings
:
bJson
,
Settings
:
bJson
,
...
...
pkg/services/alerting/rule.go
View file @
f132e929
...
@@ -7,8 +7,6 @@ import (
...
@@ -7,8 +7,6 @@ import (
"strconv"
"strconv"
"time"
"time"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/components/simplejson"
m
"github.com/grafana/grafana/pkg/models"
m
"github.com/grafana/grafana/pkg/models"
)
)
...
@@ -32,7 +30,7 @@ type Rule struct {
...
@@ -32,7 +30,7 @@ type Rule struct {
ExecutionErrorState
m
.
ExecutionErrorOption
ExecutionErrorState
m
.
ExecutionErrorOption
State
m
.
AlertStateType
State
m
.
AlertStateType
Conditions
[]
Condition
Conditions
[]
Condition
Notifications
[]
int64
Notifications
[]
string
StateChanges
int64
StateChanges
int64
}
}
...
@@ -128,22 +126,11 @@ func NewRuleFromDBAlert(ruleDef *m.Alert) (*Rule, error) {
...
@@ -128,22 +126,11 @@ func NewRuleFromDBAlert(ruleDef *m.Alert) (*Rule, error) {
for
_
,
v
:=
range
ruleDef
.
Settings
.
Get
(
"notifications"
)
.
MustArray
()
{
for
_
,
v
:=
range
ruleDef
.
Settings
.
Get
(
"notifications"
)
.
MustArray
()
{
jsonModel
:=
simplejson
.
NewFromAny
(
v
)
jsonModel
:=
simplejson
.
NewFromAny
(
v
)
id
,
err
:=
jsonModel
.
Get
(
"id"
)
.
Int64
()
uid
,
err
:=
jsonModel
.
Get
(
"uid"
)
.
String
()
if
err
!=
nil
{
if
err
!=
nil
{
notificationName
,
notificationNameErr
:=
jsonModel
.
Get
(
"name"
)
.
String
()
if
notificationNameErr
!=
nil
{
return
nil
,
ValidationError
{
Reason
:
"Invalid notification schema"
,
DashboardId
:
model
.
DashboardId
,
Alertid
:
model
.
Id
,
PanelId
:
model
.
PanelId
}
return
nil
,
ValidationError
{
Reason
:
"Invalid notification schema"
,
DashboardId
:
model
.
DashboardId
,
Alertid
:
model
.
Id
,
PanelId
:
model
.
PanelId
}
}
}
cmd
:=
&
m
.
GetAlertNotificationsQuery
{
OrgId
:
ruleDef
.
OrgId
,
Name
:
notificationName
}
model
.
Notifications
=
append
(
model
.
Notifications
,
uid
)
nameErr
:=
bus
.
Dispatch
(
cmd
)
if
nameErr
!=
nil
||
cmd
.
Result
==
nil
{
errorMsg
:=
fmt
.
Sprintf
(
"Cannot lookup notification by name %s and orgId %d"
,
notificationName
,
ruleDef
.
OrgId
)
return
nil
,
ValidationError
{
Reason
:
errorMsg
,
DashboardId
:
model
.
DashboardId
,
Alertid
:
model
.
Id
,
PanelId
:
model
.
PanelId
}
}
model
.
Notifications
=
append
(
model
.
Notifications
,
cmd
.
Result
.
Id
)
}
else
{
model
.
Notifications
=
append
(
model
.
Notifications
,
id
)
}
}
}
...
...
pkg/services/alerting/rule_test.go
View file @
f132e929
...
@@ -3,17 +3,11 @@ package alerting
...
@@ -3,17 +3,11 @@ package alerting
import
(
import
(
"testing"
"testing"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/models"
m
"github.com/grafana/grafana/pkg/models"
m
"github.com/grafana/grafana/pkg/models"
.
"github.com/smartystreets/goconvey/convey"
.
"github.com/smartystreets/goconvey/convey"
)
)
var
(
fakeRepo
*
fakeRepository
)
type
FakeCondition
struct
{}
type
FakeCondition
struct
{}
func
(
f
*
FakeCondition
)
Eval
(
context
*
EvalContext
)
(
*
ConditionResult
,
error
)
{
func
(
f
*
FakeCondition
)
Eval
(
context
*
EvalContext
)
(
*
ConditionResult
,
error
)
{
...
@@ -78,8 +72,8 @@ func TestAlertRuleModel(t *testing.T) {
...
@@ -78,8 +72,8 @@ func TestAlertRuleModel(t *testing.T) {
}
}
],
],
"notifications": [
"notifications": [
{"
id": 1134
},
{"
uid": "1134"
},
{"
id": 22
}
{"
uid": "22"
}
]
]
}
}
`
`
...
@@ -135,155 +129,6 @@ func TestAlertRuleModel(t *testing.T) {
...
@@ -135,155 +129,6 @@ func TestAlertRuleModel(t *testing.T) {
So
(
err
,
ShouldBeNil
)
So
(
err
,
ShouldBeNil
)
So
(
alertRule
.
Frequency
,
ShouldEqual
,
60
)
So
(
alertRule
.
Frequency
,
ShouldEqual
,
60
)
})
})
Convey
(
"can construct alert rule model mixed notification ids and names"
,
func
()
{
json
:=
`
{
"name": "name2",
"description": "desc2",
"handler": 0,
"noDataMode": "critical",
"enabled": true,
"frequency": "60s",
"conditions": [
{
"type": "test",
"prop": 123
}
],
"notifications": [
{"id": 1134},
{"id": 22},
{"name": "channel1"},
{"name": "channel2"}
]
}
`
alertJSON
,
jsonErr
:=
simplejson
.
NewJson
([]
byte
(
json
))
So
(
jsonErr
,
ShouldBeNil
)
alert
:=
&
m
.
Alert
{
Id
:
1
,
OrgId
:
1
,
DashboardId
:
1
,
PanelId
:
1
,
Settings
:
alertJSON
,
}
fakeRepo
=
&
fakeRepository
{}
bus
.
ClearBusHandlers
()
bus
.
AddHandler
(
"test"
,
mockGet
)
fakeRepo
.
loadAll
=
[]
*
models
.
AlertNotification
{
{
Name
:
"channel1"
,
OrgId
:
1
,
Id
:
1
},
{
Name
:
"channel2"
,
OrgId
:
1
,
Id
:
2
},
}
alertRule
,
err
:=
NewRuleFromDBAlert
(
alert
)
So
(
err
,
ShouldBeNil
)
Convey
(
"Can read notifications"
,
func
()
{
So
(
len
(
alertRule
.
Notifications
),
ShouldEqual
,
4
)
So
(
alertRule
.
Notifications
,
ShouldResemble
,
[]
int64
{
1134
,
22
,
1
,
2
})
})
})
})
Convey
(
"raise error in case of left id"
,
func
()
{
json
:=
`
{
"name": "name2",
"description": "desc2",
"handler": 0,
"noDataMode": "critical",
"enabled": true,
"frequency": "60s",
"conditions": [
{
"type": "test",
"prop": 123
}
],
"notifications": [
{"not_id": 1134}
]
}
`
alertJSON
,
jsonErr
:=
simplejson
.
NewJson
([]
byte
(
json
))
So
(
jsonErr
,
ShouldBeNil
)
alert
:=
&
m
.
Alert
{
Id
:
1
,
OrgId
:
1
,
DashboardId
:
1
,
PanelId
:
1
,
Settings
:
alertJSON
,
}
_
,
err
:=
NewRuleFromDBAlert
(
alert
)
So
(
err
,
ShouldNotBeNil
)
})
Convey
(
"raise error in case of left id but existed name with alien orgId"
,
func
()
{
json
:=
`
{
"name": "name2",
"description": "desc2",
"handler": 0,
"noDataMode": "critical",
"enabled": true,
"frequency": "60s",
"conditions": [
{
"type": "test",
"prop": 123
}
],
"notifications": [
{"not_id": 1134, "name": "channel1"}
]
}
`
alertJSON
,
jsonErr
:=
simplejson
.
NewJson
([]
byte
(
json
))
So
(
jsonErr
,
ShouldBeNil
)
alert
:=
&
m
.
Alert
{
Id
:
1
,
OrgId
:
1
,
DashboardId
:
1
,
PanelId
:
1
,
Settings
:
alertJSON
,
}
fakeRepo
=
&
fakeRepository
{}
bus
.
ClearBusHandlers
()
bus
.
AddHandler
(
"test"
,
mockGet
)
fakeRepo
.
loadAll
=
[]
*
models
.
AlertNotification
{
{
Name
:
"channel1"
,
OrgId
:
2
,
Id
:
1
},
}
_
,
err
:=
NewRuleFromDBAlert
(
alert
)
So
(
err
,
ShouldNotBeNil
)
})
})
}
type
fakeRepository
struct
{
loadAll
[]
*
models
.
AlertNotification
}
func
mockGet
(
cmd
*
models
.
GetAlertNotificationsQuery
)
error
{
for
_
,
v
:=
range
fakeRepo
.
loadAll
{
if
cmd
.
Name
==
v
.
Name
&&
cmd
.
OrgId
==
v
.
OrgId
{
cmd
.
Result
=
v
return
nil
}
}
return
nil
}
}
pkg/services/alerting/testdata/dash-without-id.json
View file @
f132e929
...
@@ -44,7 +44,7 @@
...
@@ -44,7 +44,7 @@
"noDataState"
:
"no_data"
,
"noDataState"
:
"no_data"
,
"notifications"
:
[
"notifications"
:
[
{
{
"
id"
:
6
"
uid"
:
"notifier1"
}
}
]
]
},
},
...
...
pkg/services/alerting/testdata/influxdb-alert.json
View file @
f132e929
...
@@ -45,7 +45,7 @@
...
@@ -45,7 +45,7 @@
"noDataState"
:
"no_data"
,
"noDataState"
:
"no_data"
,
"notifications"
:
[
"notifications"
:
[
{
{
"
id"
:
6
"
uid"
:
"notifier1"
}
}
]
]
},
},
...
...
pkg/services/provisioning/alert_notifications/alert_notifications.go
View file @
f132e929
...
@@ -44,7 +44,7 @@ func (dc *NotificationProvisioner) apply(cfg *notificationsAsConfig) error {
...
@@ -44,7 +44,7 @@ func (dc *NotificationProvisioner) apply(cfg *notificationsAsConfig) error {
func
(
dc
*
NotificationProvisioner
)
deleteNotifications
(
notificationToDelete
[]
*
deleteNotificationConfig
)
error
{
func
(
dc
*
NotificationProvisioner
)
deleteNotifications
(
notificationToDelete
[]
*
deleteNotificationConfig
)
error
{
for
_
,
notification
:=
range
notificationToDelete
{
for
_
,
notification
:=
range
notificationToDelete
{
dc
.
log
.
Info
(
"Deleting alert notification"
,
"name"
,
notification
.
Name
)
dc
.
log
.
Info
(
"Deleting alert notification"
,
"name"
,
notification
.
Name
,
"uid"
,
notification
.
Uid
)
if
notification
.
OrgId
==
0
&&
notification
.
OrgName
!=
""
{
if
notification
.
OrgId
==
0
&&
notification
.
OrgName
!=
""
{
getOrg
:=
&
models
.
GetOrgByNameQuery
{
Name
:
notification
.
OrgName
}
getOrg
:=
&
models
.
GetOrgByNameQuery
{
Name
:
notification
.
OrgName
}
...
@@ -55,14 +55,14 @@ func (dc *NotificationProvisioner) deleteNotifications(notificationToDelete []*d
...
@@ -55,14 +55,14 @@ func (dc *NotificationProvisioner) deleteNotifications(notificationToDelete []*d
}
else
if
notification
.
OrgId
<
0
{
}
else
if
notification
.
OrgId
<
0
{
notification
.
OrgId
=
1
notification
.
OrgId
=
1
}
}
getNotification
:=
&
models
.
GetAlertNotifications
Query
{
Name
:
notification
.
Name
,
OrgId
:
notification
.
OrgId
}
getNotification
:=
&
models
.
GetAlertNotifications
WithUidQuery
{
Uid
:
notification
.
Uid
,
OrgId
:
notification
.
OrgId
}
if
err
:=
bus
.
Dispatch
(
getNotification
);
err
!=
nil
{
if
err
:=
bus
.
Dispatch
(
getNotification
);
err
!=
nil
{
return
err
return
err
}
}
if
getNotification
.
Result
!=
nil
{
if
getNotification
.
Result
!=
nil
{
cmd
:=
&
models
.
DeleteAlertNotification
Command
{
Id
:
getNotification
.
Result
.
I
d
,
OrgId
:
getNotification
.
OrgId
}
cmd
:=
&
models
.
DeleteAlertNotification
WithUidCommand
{
Uid
:
getNotification
.
Result
.
Ui
d
,
OrgId
:
getNotification
.
OrgId
}
if
err
:=
bus
.
Dispatch
(
cmd
);
err
!=
nil
{
if
err
:=
bus
.
Dispatch
(
cmd
);
err
!=
nil
{
return
err
return
err
}
}
...
@@ -85,33 +85,40 @@ func (dc *NotificationProvisioner) mergeNotifications(notificationToMerge []*not
...
@@ -85,33 +85,40 @@ func (dc *NotificationProvisioner) mergeNotifications(notificationToMerge []*not
notification
.
OrgId
=
1
notification
.
OrgId
=
1
}
}
cmd
:=
&
models
.
GetAlertNotifications
Query
{
OrgId
:
notification
.
OrgId
,
Name
:
notification
.
Name
}
cmd
:=
&
models
.
GetAlertNotifications
WithUidQuery
{
OrgId
:
notification
.
OrgId
,
Uid
:
notification
.
Uid
}
err
:=
bus
.
Dispatch
(
cmd
)
err
:=
bus
.
Dispatch
(
cmd
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
if
cmd
.
Result
==
nil
{
if
cmd
.
Result
==
nil
{
dc
.
log
.
Info
(
"Inserting alert notification from configuration "
,
"name"
,
notification
.
Name
)
dc
.
log
.
Info
(
"Inserting alert notification from configuration "
,
"name"
,
notification
.
Name
,
"uid"
,
notification
.
Uid
)
insertCmd
:=
&
models
.
CreateAlertNotificationCommand
{
insertCmd
:=
&
models
.
CreateAlertNotificationCommand
{
Uid
:
notification
.
Uid
,
Name
:
notification
.
Name
,
Name
:
notification
.
Name
,
Type
:
notification
.
Type
,
Type
:
notification
.
Type
,
IsDefault
:
notification
.
IsDefault
,
IsDefault
:
notification
.
IsDefault
,
Settings
:
notification
.
SettingsToJson
(),
Settings
:
notification
.
SettingsToJson
(),
OrgId
:
notification
.
OrgId
,
OrgId
:
notification
.
OrgId
,
DisableResolveMessage
:
notification
.
DisableResolveMessage
,
Frequency
:
notification
.
Frequency
,
SendReminder
:
notification
.
SendReminder
,
}
}
if
err
:=
bus
.
Dispatch
(
insertCmd
);
err
!=
nil
{
if
err
:=
bus
.
Dispatch
(
insertCmd
);
err
!=
nil
{
return
err
return
err
}
}
}
else
{
}
else
{
dc
.
log
.
Info
(
"Updating alert notification from configuration"
,
"name"
,
notification
.
Name
)
dc
.
log
.
Info
(
"Updating alert notification from configuration"
,
"name"
,
notification
.
Name
)
updateCmd
:=
&
models
.
UpdateAlertNotificationCommand
{
updateCmd
:=
&
models
.
UpdateAlertNotification
WithUid
Command
{
Id
:
cmd
.
Result
.
I
d
,
Uid
:
notification
.
Ui
d
,
Name
:
notification
.
Name
,
Name
:
notification
.
Name
,
Type
:
notification
.
Type
,
Type
:
notification
.
Type
,
IsDefault
:
notification
.
IsDefault
,
IsDefault
:
notification
.
IsDefault
,
Settings
:
notification
.
SettingsToJson
(),
Settings
:
notification
.
SettingsToJson
(),
OrgId
:
notification
.
OrgId
,
OrgId
:
notification
.
OrgId
,
DisableResolveMessage
:
notification
.
DisableResolveMessage
,
Frequency
:
notification
.
Frequency
,
SendReminder
:
notification
.
SendReminder
,
}
}
if
err
:=
bus
.
Dispatch
(
updateCmd
);
err
!=
nil
{
if
err
:=
bus
.
Dispatch
(
updateCmd
);
err
!=
nil
{
return
err
return
err
...
@@ -130,17 +137,22 @@ func (cfg *notificationsAsConfig) mapToNotificationFromConfig() *notificationsAs
...
@@ -130,17 +137,22 @@ func (cfg *notificationsAsConfig) mapToNotificationFromConfig() *notificationsAs
for
_
,
notification
:=
range
cfg
.
Notifications
{
for
_
,
notification
:=
range
cfg
.
Notifications
{
r
.
Notifications
=
append
(
r
.
Notifications
,
&
notificationFromConfig
{
r
.
Notifications
=
append
(
r
.
Notifications
,
&
notificationFromConfig
{
Uid
:
notification
.
Uid
,
OrgId
:
notification
.
OrgId
,
OrgId
:
notification
.
OrgId
,
OrgName
:
notification
.
OrgName
,
OrgName
:
notification
.
OrgName
,
Name
:
notification
.
Name
,
Name
:
notification
.
Name
,
Type
:
notification
.
Type
,
Type
:
notification
.
Type
,
IsDefault
:
notification
.
IsDefault
,
IsDefault
:
notification
.
IsDefault
,
Settings
:
notification
.
Settings
,
Settings
:
notification
.
Settings
,
DisableResolveMessage
:
notification
.
DisableResolveMessage
,
Frequency
:
notification
.
Frequency
,
SendReminder
:
notification
.
SendReminder
,
})
})
}
}
for
_
,
notification
:=
range
cfg
.
DeleteNotifications
{
for
_
,
notification
:=
range
cfg
.
DeleteNotifications
{
r
.
DeleteNotifications
=
append
(
r
.
DeleteNotifications
,
&
deleteNotificationConfig
{
r
.
DeleteNotifications
=
append
(
r
.
DeleteNotifications
,
&
deleteNotificationConfig
{
Uid
:
notification
.
Uid
,
OrgId
:
notification
.
OrgId
,
OrgId
:
notification
.
OrgId
,
OrgName
:
notification
.
OrgName
,
OrgName
:
notification
.
OrgName
,
Name
:
notification
.
Name
,
Name
:
notification
.
Name
,
...
...
pkg/services/provisioning/alert_notifications/config_reader.go
View file @
f132e929
package
alert_notifications
package
alert_notifications
import
(
import
(
"fmt"
"io/ioutil"
"io/ioutil"
"os"
"os"
"path/filepath"
"path/filepath"
...
@@ -41,7 +42,11 @@ func (cr *configReader) readConfig(path string) ([]*notificationsAsConfig, error
...
@@ -41,7 +42,11 @@ func (cr *configReader) readConfig(path string) ([]*notificationsAsConfig, error
}
}
cr
.
log
.
Debug
(
"Validating alert notifications"
)
cr
.
log
.
Debug
(
"Validating alert notifications"
)
validateOrgIdAndSet
(
notifications
)
if
err
=
validateRequiredField
(
notifications
);
err
!=
nil
{
return
nil
,
err
}
checkOrgIdAndOrgName
(
notifications
)
err
=
validateNotifications
(
notifications
)
err
=
validateNotifications
(
notifications
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -67,7 +72,7 @@ func (cr *configReader) parseNotificationConfig(path string, file os.FileInfo) (
...
@@ -67,7 +72,7 @@ func (cr *configReader) parseNotificationConfig(path string, file os.FileInfo) (
return
cfg
.
mapToNotificationFromConfig
(),
nil
return
cfg
.
mapToNotificationFromConfig
(),
nil
}
}
func
validateOrgIdAndSet
(
notifications
[]
*
notificationsAsConfig
)
{
func
checkOrgIdAndOrgName
(
notifications
[]
*
notificationsAsConfig
)
{
for
i
:=
range
notifications
{
for
i
:=
range
notifications
{
for
_
,
notification
:=
range
notifications
[
i
]
.
Notifications
{
for
_
,
notification
:=
range
notifications
[
i
]
.
Notifications
{
if
notification
.
OrgId
<
1
{
if
notification
.
OrgId
<
1
{
...
@@ -91,6 +96,44 @@ func validateOrgIdAndSet(notifications []*notificationsAsConfig) {
...
@@ -91,6 +96,44 @@ func validateOrgIdAndSet(notifications []*notificationsAsConfig) {
}
}
}
}
func
validateRequiredField
(
notifications
[]
*
notificationsAsConfig
)
error
{
for
i
:=
range
notifications
{
var
errStrings
[]
string
for
index
,
notification
:=
range
notifications
[
i
]
.
Notifications
{
if
notification
.
Name
==
""
{
errStrings
=
append
(
errStrings
,
fmt
.
Sprintf
(
"Added alert notification item %d in configuration doesn't contain required field name"
,
index
+
1
),
)
}
if
notification
.
Uid
==
""
{
errStrings
=
append
(
errStrings
,
fmt
.
Sprintf
(
"Added alert notification item %d in configuration doesn't contain required field uid"
,
index
+
1
),
)
}
}
for
index
,
notification
:=
range
notifications
[
i
]
.
DeleteNotifications
{
if
notification
.
Name
==
""
{
errStrings
=
append
(
errStrings
,
fmt
.
Sprintf
(
"Deleted alert notification item %d in configuration doesn't contain required field name"
,
index
+
1
),
)
}
if
notification
.
Uid
==
""
{
errStrings
=
append
(
errStrings
,
fmt
.
Sprintf
(
"Deleted alert notification item %d in configuration doesn't contain required field uid"
,
index
+
1
),
)
}
}
if
len
(
errStrings
)
!=
0
{
return
fmt
.
Errorf
(
strings
.
Join
(
errStrings
,
"
\n
"
))
}
}
return
nil
}
func
validateNotifications
(
notifications
[]
*
notificationsAsConfig
)
error
{
func
validateNotifications
(
notifications
[]
*
notificationsAsConfig
)
error
{
notifierTypes
:=
alerting
.
GetNotifiers
()
notifierTypes
:=
alerting
.
GetNotifiers
()
...
...
pkg/services/provisioning/alert_notifications/config_reader_test.go
View file @
f132e929
This diff is collapsed.
Click to expand it.
pkg/services/provisioning/alert_notifications/test-configs/correct-properties-with-orgName/correct-properties-with-orgName.yaml
View file @
f132e929
alert_notifications
:
alert_notifications
:
-
name
:
default-slack-notification
-
name
:
default-notification-create
type
:
slack
org_name
:
Main Org. 1
is_default
:
true
settings
:
recipient
:
"
XXX"
token
:
"
xoxb"
uploadImage
:
true
url
:
https://slack.com
-
name
:
another-not-default-notification
type
:
email
type
:
email
uid
:
notifier2
settings
:
settings
:
addresses
:
example@example.com
addresses
:
example@example.com
org_name
:
Main Org. 2
org_name
:
Main Org. 2
is_default
:
false
is_default
:
false
delete_alert_notifications
:
delete_alert_notifications
:
-
name
:
default-slack-notification
-
name
:
default-notification-delete
org_name
:
Main Org. 1
-
name
:
another-not-default-notification
org_name
:
Main Org. 2
org_name
:
Main Org. 2
uid
:
notifier2
\ No newline at end of file
pkg/services/provisioning/alert_notifications/test-configs/correct-properties/correct-properties.yaml
View file @
f132e929
alert_notifications
:
alert_notifications
:
-
name
:
default-slack-notification
-
name
:
default-slack-notification
type
:
slack
type
:
slack
uid
:
notifier1
org_id
:
2
org_id
:
2
uid
:
"
notifier1"
is_default
:
true
is_default
:
true
settings
:
settings
:
recipient
:
"
XXX"
recipient
:
"
XXX"
...
@@ -13,21 +15,28 @@ alert_notifications:
...
@@ -13,21 +15,28 @@ alert_notifications:
settings
:
settings
:
addresses
:
example@exmaple.com
addresses
:
example@exmaple.com
org_id
:
3
org_id
:
3
uid
:
"
notifier2"
is_default
:
false
is_default
:
false
-
name
:
check-unset-is_default-is-false
-
name
:
check-unset-is_default-is-false
type
:
slack
type
:
slack
org_id
:
3
org_id
:
3
uid
:
"
notifier3"
settings
:
settings
:
url
:
https://slack.com
url
:
https://slack.com
-
name
:
Added notification with whitespaces in name
-
name
:
Added notification with whitespaces in name
type
:
email
type
:
email
org_id
:
3
org_id
:
3
uid
:
"
notifier4"
settings
:
settings
:
addresses
:
example@exmaple.com
addresses
:
example@exmaple.com
delete_alert_notifications
:
delete_alert_notifications
:
-
name
:
default-slack-notification
-
name
:
default-slack-notification
org_id
:
2
org_id
:
2
uid
:
notifier1
-
name
:
deleted-notification-without-orgId
-
name
:
deleted-notification-without-orgId
uid
:
"
notifier2"
-
name
:
deleted-notification-with-0-orgId
-
name
:
deleted-notification-with-0-orgId
org_id
:
0
org_id
:
0
uid
:
"
notifier3"
-
name
:
Deleted notification with whitespaces in name
-
name
:
Deleted notification with whitespaces in name
uid
:
"
notifier4"
\ No newline at end of file
pkg/services/provisioning/alert_notifications/test-configs/double-default/default-1.yml
View file @
f132e929
alert_notifications
:
alert_notifications
:
-
name
:
first-default
-
name
:
first-default
type
:
slack
type
:
slack
uid
:
notifier1
is_default
:
true
is_default
:
true
settings
:
settings
:
url
:
https://slack.com
url
:
https://slack.com
\ No newline at end of file
pkg/services/provisioning/alert_notifications/test-configs/double-default/default-2.yaml
View file @
f132e929
alert_notifications
:
alert_notifications
:
-
name
:
second-default
-
name
:
second-default
type
:
email
type
:
email
uid
:
notifier2
is_default
:
true
is_default
:
true
settings
:
settings
:
addresses
:
example@example.com
addresses
:
example@example.com
\ No newline at end of file
pkg/services/provisioning/alert_notifications/test-configs/incorrect-
properties/incorrect-propertie
s.yaml
→
pkg/services/provisioning/alert_notifications/test-configs/incorrect-
settings/incorrect-setting
s.yaml
View file @
f132e929
...
@@ -2,6 +2,7 @@ alert_notifications:
...
@@ -2,6 +2,7 @@ alert_notifications:
-
name
:
slack-notification-without-url-in-settings
-
name
:
slack-notification-without-url-in-settings
type
:
slack
type
:
slack
org_id
:
2
org_id
:
2
uid
:
notifier1
is_default
:
true
is_default
:
true
settings
:
settings
:
recipient
:
"
XXX"
recipient
:
"
XXX"
...
...
pkg/services/provisioning/alert_notifications/test-configs/no-required-fields/no-required-fields.yaml
0 → 100644
View file @
f132e929
alert_notifications
:
-
type
:
slack
org_id
:
2
uid
:
no-name_added-notification
is_default
:
true
settings
:
recipient
:
"
XXX"
token
:
"
xoxb"
uploadImage
:
true
-
name
:
no-uid
type
:
slack
org_id
:
2
is_default
:
true
settings
:
recipient
:
"
XXX"
token
:
"
xoxb"
uploadImage
:
true
delete_alert_notifications
:
-
name
:
no-uid
type
:
slack
org_id
:
2
is_default
:
true
settings
:
recipient
:
"
XXX"
token
:
"
xoxb"
uploadImage
:
true
-
type
:
slack
org_id
:
2
uid
:
no-name_added-notification
is_default
:
true
settings
:
recipient
:
"
XXX"
token
:
"
xoxb"
uploadImage
:
true
\ No newline at end of file
pkg/services/provisioning/alert_notifications/test-configs/two-notifications/two-notifications.yaml
View file @
f132e929
alert_notifications
:
alert_notifications
:
-
name
:
channel1
-
name
:
channel1
type
:
slack
settings
:
url
:
http://slack.com
-
name
:
channel2
type
:
email
type
:
email
uid
:
notifier1
org_id
:
1
settings
:
settings
:
addresses
:
example@example.com
addresses
:
example@example.com
-
name
:
channel2
type
:
slack
uid
:
notifier2
settings
:
url
:
http://slack.com
pkg/services/provisioning/alert_notifications/test-configs/unknown-notifier/notification.yaml
View file @
f132e929
alert_notifications
:
alert_notifications
:
-
name
:
unknown-notifier
-
name
:
unknown-notifier
type
:
nonexisting
type
:
nonexisting
uid
:
notifier1
\ No newline at end of file
pkg/services/provisioning/alert_notifications/types.go
View file @
f132e929
...
@@ -8,16 +8,21 @@ type notificationsAsConfig struct {
...
@@ -8,16 +8,21 @@ type notificationsAsConfig struct {
}
}
type
deleteNotificationConfig
struct
{
type
deleteNotificationConfig
struct
{
Uid
string
`json:"uid" yaml:"uid"`
Name
string
`json:"name" yaml:"name"`
Name
string
`json:"name" yaml:"name"`
OrgId
int64
`json:"org_id" yaml:"org_id"`
OrgId
int64
`json:"org_id" yaml:"org_id"`
OrgName
string
`json:"org_name" yaml:"org_name"`
OrgName
string
`json:"org_name" yaml:"org_name"`
}
}
type
notificationFromConfig
struct
{
type
notificationFromConfig
struct
{
Uid
string
`json:"uid" yaml:"uid"`
OrgId
int64
`json:"org_id" yaml:"org_id"`
OrgId
int64
`json:"org_id" yaml:"org_id"`
OrgName
string
`json:"org_name" yaml:"org_name"`
OrgName
string
`json:"org_name" yaml:"org_name"`
Name
string
`json:"name" yaml:"name"`
Name
string
`json:"name" yaml:"name"`
Type
string
`json:"type" yaml:"type"`
Type
string
`json:"type" yaml:"type"`
SendReminder
bool
`json:"send_reminder" yaml:"send_reminder"`
DisableResolveMessage
bool
`json:"disable_resolve_message" yaml:"disable_resolve_message"`
Frequency
string
`json:"frequency" yaml:"frequency"`
IsDefault
bool
`json:"is_default" yaml:"is_default"`
IsDefault
bool
`json:"is_default" yaml:"is_default"`
Settings
map
[
string
]
interface
{}
`json:"settings" yaml:"settings"`
Settings
map
[
string
]
interface
{}
`json:"settings" yaml:"settings"`
}
}
...
...
pkg/services/sqlstore/alert_notification.go
View file @
f132e929
...
@@ -10,6 +10,7 @@ import (
...
@@ -10,6 +10,7 @@ import (
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/bus"
m
"github.com/grafana/grafana/pkg/models"
m
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/util"
)
)
func
init
()
{
func
init
()
{
...
@@ -17,11 +18,15 @@ func init() {
...
@@ -17,11 +18,15 @@ func init() {
bus
.
AddHandler
(
"sql"
,
CreateAlertNotificationCommand
)
bus
.
AddHandler
(
"sql"
,
CreateAlertNotificationCommand
)
bus
.
AddHandler
(
"sql"
,
UpdateAlertNotification
)
bus
.
AddHandler
(
"sql"
,
UpdateAlertNotification
)
bus
.
AddHandler
(
"sql"
,
DeleteAlertNotification
)
bus
.
AddHandler
(
"sql"
,
DeleteAlertNotification
)
bus
.
AddHandler
(
"sql"
,
GetAlertNotificationsToSend
)
bus
.
AddHandler
(
"sql"
,
GetAllAlertNotifications
)
bus
.
AddHandler
(
"sql"
,
GetAllAlertNotifications
)
bus
.
AddHandlerCtx
(
"sql"
,
GetOrCreateAlertNotificationState
)
bus
.
AddHandlerCtx
(
"sql"
,
GetOrCreateAlertNotificationState
)
bus
.
AddHandlerCtx
(
"sql"
,
SetAlertNotificationStateToCompleteCommand
)
bus
.
AddHandlerCtx
(
"sql"
,
SetAlertNotificationStateToCompleteCommand
)
bus
.
AddHandlerCtx
(
"sql"
,
SetAlertNotificationStateToPendingCommand
)
bus
.
AddHandlerCtx
(
"sql"
,
SetAlertNotificationStateToPendingCommand
)
bus
.
AddHandler
(
"sql"
,
GetAlertNotificationsWithUid
)
bus
.
AddHandler
(
"sql"
,
UpdateAlertNotificationWithUid
)
bus
.
AddHandler
(
"sql"
,
DeleteAlertNotificationWithUid
)
bus
.
AddHandler
(
"sql"
,
GetAlertNotificationsWithUidToSend
)
}
}
func
DeleteAlertNotification
(
cmd
*
m
.
DeleteAlertNotificationCommand
)
error
{
func
DeleteAlertNotification
(
cmd
*
m
.
DeleteAlertNotificationCommand
)
error
{
...
@@ -39,10 +44,33 @@ func DeleteAlertNotification(cmd *m.DeleteAlertNotificationCommand) error {
...
@@ -39,10 +44,33 @@ func DeleteAlertNotification(cmd *m.DeleteAlertNotificationCommand) error {
})
})
}
}
func
DeleteAlertNotificationWithUid
(
cmd
*
m
.
DeleteAlertNotificationWithUidCommand
)
error
{
existingNotification
:=
&
m
.
GetAlertNotificationsWithUidQuery
{
OrgId
:
cmd
.
OrgId
,
Uid
:
cmd
.
Uid
}
if
getNotificationErr
:=
getAlertNotificationWithUidInternal
(
existingNotification
,
newSession
());
getNotificationErr
!=
nil
{
return
getNotificationErr
}
if
existingNotification
.
Result
!=
nil
{
deleteCommand
:=
&
m
.
DeleteAlertNotificationCommand
{
Id
:
existingNotification
.
Result
.
Id
,
OrgId
:
existingNotification
.
Result
.
OrgId
,
}
if
deleteErr
:=
bus
.
Dispatch
(
deleteCommand
);
deleteErr
!=
nil
{
return
deleteErr
}
}
return
nil
}
func
GetAlertNotifications
(
query
*
m
.
GetAlertNotificationsQuery
)
error
{
func
GetAlertNotifications
(
query
*
m
.
GetAlertNotificationsQuery
)
error
{
return
getAlertNotificationInternal
(
query
,
newSession
())
return
getAlertNotificationInternal
(
query
,
newSession
())
}
}
func
GetAlertNotificationsWithUid
(
query
*
m
.
GetAlertNotificationsWithUidQuery
)
error
{
return
getAlertNotificationWithUidInternal
(
query
,
newSession
())
}
func
GetAllAlertNotifications
(
query
*
m
.
GetAllAlertNotificationsQuery
)
error
{
func
GetAllAlertNotifications
(
query
*
m
.
GetAllAlertNotificationsQuery
)
error
{
results
:=
make
([]
*
m
.
AlertNotification
,
0
)
results
:=
make
([]
*
m
.
AlertNotification
,
0
)
if
err
:=
x
.
Where
(
"org_id = ?"
,
query
.
OrgId
)
.
Find
(
&
results
);
err
!=
nil
{
if
err
:=
x
.
Where
(
"org_id = ?"
,
query
.
OrgId
)
.
Find
(
&
results
);
err
!=
nil
{
...
@@ -53,12 +81,13 @@ func GetAllAlertNotifications(query *m.GetAllAlertNotificationsQuery) error {
...
@@ -53,12 +81,13 @@ func GetAllAlertNotifications(query *m.GetAllAlertNotificationsQuery) error {
return
nil
return
nil
}
}
func
GetAlertNotifications
ToSend
(
query
*
m
.
GetAlertNotifications
ToSendQuery
)
error
{
func
GetAlertNotifications
WithUidToSend
(
query
*
m
.
GetAlertNotificationsWithUid
ToSendQuery
)
error
{
var
sql
bytes
.
Buffer
var
sql
bytes
.
Buffer
params
:=
make
([]
interface
{},
0
)
params
:=
make
([]
interface
{},
0
)
sql
.
WriteString
(
`SELECT
sql
.
WriteString
(
`SELECT
alert_notification.id,
alert_notification.id,
alert_notification.uid,
alert_notification.org_id,
alert_notification.org_id,
alert_notification.name,
alert_notification.name,
alert_notification.type,
alert_notification.type,
...
@@ -77,9 +106,10 @@ func GetAlertNotificationsToSend(query *m.GetAlertNotificationsToSendQuery) erro
...
@@ -77,9 +106,10 @@ func GetAlertNotificationsToSend(query *m.GetAlertNotificationsToSendQuery) erro
sql
.
WriteString
(
` AND ((alert_notification.is_default = ?)`
)
sql
.
WriteString
(
` AND ((alert_notification.is_default = ?)`
)
params
=
append
(
params
,
dialect
.
BooleanStr
(
true
))
params
=
append
(
params
,
dialect
.
BooleanStr
(
true
))
if
len
(
query
.
Ids
)
>
0
{
sql
.
WriteString
(
` OR alert_notification.id IN (?`
+
strings
.
Repeat
(
",?"
,
len
(
query
.
Ids
)
-
1
)
+
")"
)
if
len
(
query
.
Uids
)
>
0
{
for
_
,
v
:=
range
query
.
Ids
{
sql
.
WriteString
(
` OR alert_notification.uid IN (?`
+
strings
.
Repeat
(
",?"
,
len
(
query
.
Uids
)
-
1
)
+
")"
)
for
_
,
v
:=
range
query
.
Uids
{
params
=
append
(
params
,
v
)
params
=
append
(
params
,
v
)
}
}
}
}
...
@@ -142,16 +172,70 @@ func getAlertNotificationInternal(query *m.GetAlertNotificationsQuery, sess *DBS
...
@@ -142,16 +172,70 @@ func getAlertNotificationInternal(query *m.GetAlertNotificationsQuery, sess *DBS
return
nil
return
nil
}
}
func
getAlertNotificationWithUidInternal
(
query
*
m
.
GetAlertNotificationsWithUidQuery
,
sess
*
DBSession
)
error
{
var
sql
bytes
.
Buffer
params
:=
make
([]
interface
{},
0
)
sql
.
WriteString
(
`SELECT
alert_notification.id,
alert_notification.uid,
alert_notification.org_id,
alert_notification.name,
alert_notification.type,
alert_notification.created,
alert_notification.updated,
alert_notification.settings,
alert_notification.is_default,
alert_notification.disable_resolve_message,
alert_notification.send_reminder,
alert_notification.frequency
FROM alert_notification
`
)
sql
.
WriteString
(
` WHERE alert_notification.org_id = ? AND alert_notification.uid = ?`
)
params
=
append
(
params
,
query
.
OrgId
,
query
.
Uid
)
results
:=
make
([]
*
m
.
AlertNotification
,
0
)
if
err
:=
sess
.
SQL
(
sql
.
String
(),
params
...
)
.
Find
(
&
results
);
err
!=
nil
{
return
err
}
if
len
(
results
)
==
0
{
query
.
Result
=
nil
}
else
{
query
.
Result
=
results
[
0
]
}
return
nil
}
func
CreateAlertNotificationCommand
(
cmd
*
m
.
CreateAlertNotificationCommand
)
error
{
func
CreateAlertNotificationCommand
(
cmd
*
m
.
CreateAlertNotificationCommand
)
error
{
return
inTransaction
(
func
(
sess
*
DBSession
)
error
{
return
inTransaction
(
func
(
sess
*
DBSession
)
error
{
existingQuery
:=
&
m
.
GetAlertNotificationsQuery
{
OrgId
:
cmd
.
OrgId
,
Name
:
cmd
.
Name
}
if
cmd
.
Uid
==
""
{
err
:=
getAlertNotificationInternal
(
existingQuery
,
sess
)
if
uid
,
uidGenerationErr
:=
generateNewAlertNotificationUid
(
sess
,
cmd
.
OrgId
);
uidGenerationErr
!=
nil
{
return
uidGenerationErr
}
else
{
cmd
.
Uid
=
uid
}
}
existingQuery
:=
&
m
.
GetAlertNotificationsWithUidQuery
{
OrgId
:
cmd
.
OrgId
,
Uid
:
cmd
.
Uid
}
err
:=
getAlertNotificationWithUidInternal
(
existingQuery
,
sess
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
if
existingQuery
.
Result
!=
nil
{
if
existingQuery
.
Result
!=
nil
{
return
fmt
.
Errorf
(
"Alert notification uid %s already exists"
,
cmd
.
Uid
)
}
// check if name exists
sameNameQuery
:=
&
m
.
GetAlertNotificationsQuery
{
OrgId
:
cmd
.
OrgId
,
Name
:
cmd
.
Name
}
if
err
:=
getAlertNotificationInternal
(
sameNameQuery
,
sess
);
err
!=
nil
{
return
err
}
if
sameNameQuery
.
Result
!=
nil
{
return
fmt
.
Errorf
(
"Alert notification name %s already exists"
,
cmd
.
Name
)
return
fmt
.
Errorf
(
"Alert notification name %s already exists"
,
cmd
.
Name
)
}
}
...
@@ -168,6 +252,7 @@ func CreateAlertNotificationCommand(cmd *m.CreateAlertNotificationCommand) error
...
@@ -168,6 +252,7 @@ func CreateAlertNotificationCommand(cmd *m.CreateAlertNotificationCommand) error
}
}
alertNotification
:=
&
m
.
AlertNotification
{
alertNotification
:=
&
m
.
AlertNotification
{
Uid
:
cmd
.
Uid
,
OrgId
:
cmd
.
OrgId
,
OrgId
:
cmd
.
OrgId
,
Name
:
cmd
.
Name
,
Name
:
cmd
.
Name
,
Type
:
cmd
.
Type
,
Type
:
cmd
.
Type
,
...
@@ -189,6 +274,20 @@ func CreateAlertNotificationCommand(cmd *m.CreateAlertNotificationCommand) error
...
@@ -189,6 +274,20 @@ func CreateAlertNotificationCommand(cmd *m.CreateAlertNotificationCommand) error
})
})
}
}
func
generateNewAlertNotificationUid
(
sess
*
DBSession
,
orgId
int64
)
(
string
,
error
)
{
for
i
:=
0
;
i
<
3
;
i
++
{
uid
:=
util
.
GenerateShortUid
()
exists
,
err
:=
sess
.
Where
(
"org_id=? AND uid=?"
,
orgId
,
uid
)
.
Get
(
&
m
.
AlertNotification
{})
if
err
!=
nil
{
return
""
,
err
}
if
!
exists
{
return
uid
,
nil
}
}
return
""
,
m
.
ErrAlertNotificationFailedGenerateUniqueUid
}
func
UpdateAlertNotification
(
cmd
*
m
.
UpdateAlertNotificationCommand
)
error
{
func
UpdateAlertNotification
(
cmd
*
m
.
UpdateAlertNotificationCommand
)
error
{
return
inTransaction
(
func
(
sess
*
DBSession
)
(
err
error
)
{
return
inTransaction
(
func
(
sess
*
DBSession
)
(
err
error
)
{
current
:=
m
.
AlertNotification
{}
current
:=
m
.
AlertNotification
{}
...
@@ -241,6 +340,41 @@ func UpdateAlertNotification(cmd *m.UpdateAlertNotificationCommand) error {
...
@@ -241,6 +340,41 @@ func UpdateAlertNotification(cmd *m.UpdateAlertNotificationCommand) error {
})
})
}
}
func
UpdateAlertNotificationWithUid
(
cmd
*
m
.
UpdateAlertNotificationWithUidCommand
)
error
{
getAlertNotificationWithUidQuery
:=
&
m
.
GetAlertNotificationsWithUidQuery
{
OrgId
:
cmd
.
OrgId
,
Uid
:
cmd
.
Uid
}
getCurrentNotificationErr
:=
getAlertNotificationWithUidInternal
(
getAlertNotificationWithUidQuery
,
newSession
())
if
getCurrentNotificationErr
!=
nil
{
return
getCurrentNotificationErr
}
current
:=
getAlertNotificationWithUidQuery
.
Result
if
current
==
nil
{
return
fmt
.
Errorf
(
"Cannot update, alert notification uid %s doesn't exist"
,
cmd
.
Uid
)
}
updateNotification
:=
&
m
.
UpdateAlertNotificationCommand
{
Id
:
current
.
Id
,
Name
:
cmd
.
Name
,
Type
:
cmd
.
Type
,
SendReminder
:
cmd
.
SendReminder
,
DisableResolveMessage
:
cmd
.
DisableResolveMessage
,
Frequency
:
cmd
.
Frequency
,
IsDefault
:
cmd
.
IsDefault
,
Settings
:
cmd
.
Settings
,
OrgId
:
cmd
.
OrgId
,
}
if
updateErr
:=
bus
.
Dispatch
(
updateNotification
);
updateErr
!=
nil
{
return
updateErr
}
return
nil
}
func
SetAlertNotificationStateToCompleteCommand
(
ctx
context
.
Context
,
cmd
*
m
.
SetAlertNotificationStateToCompleteCommand
)
error
{
func
SetAlertNotificationStateToCompleteCommand
(
ctx
context
.
Context
,
cmd
*
m
.
SetAlertNotificationStateToCompleteCommand
)
error
{
return
inTransactionCtx
(
ctx
,
func
(
sess
*
DBSession
)
error
{
return
inTransactionCtx
(
ctx
,
func
(
sess
*
DBSession
)
error
{
version
:=
cmd
.
Version
version
:=
cmd
.
Version
...
...
pkg/services/sqlstore/alert_notification_test.go
View file @
f132e929
...
@@ -220,11 +220,38 @@ func TestAlertNotificationSQLAccess(t *testing.T) {
...
@@ -220,11 +220,38 @@ func TestAlertNotificationSQLAccess(t *testing.T) {
So
(
cmd
.
Result
.
Type
,
ShouldEqual
,
"email"
)
So
(
cmd
.
Result
.
Type
,
ShouldEqual
,
"email"
)
So
(
cmd
.
Result
.
Frequency
,
ShouldEqual
,
10
*
time
.
Second
)
So
(
cmd
.
Result
.
Frequency
,
ShouldEqual
,
10
*
time
.
Second
)
So
(
cmd
.
Result
.
DisableResolveMessage
,
ShouldBeFalse
)
So
(
cmd
.
Result
.
DisableResolveMessage
,
ShouldBeFalse
)
So
(
cmd
.
Result
.
Uid
,
ShouldNotBeEmpty
)
Convey
(
"Cannot save Alert Notification with the same name"
,
func
()
{
Convey
(
"Cannot save Alert Notification with the same name"
,
func
()
{
err
=
CreateAlertNotificationCommand
(
cmd
)
err
=
CreateAlertNotificationCommand
(
cmd
)
So
(
err
,
ShouldNotBeNil
)
So
(
err
,
ShouldNotBeNil
)
})
})
Convey
(
"Cannot save Alert Notification with the same name and another uid"
,
func
()
{
anotherUidCmd
:=
&
models
.
CreateAlertNotificationCommand
{
Name
:
cmd
.
Name
,
Type
:
cmd
.
Type
,
OrgId
:
1
,
SendReminder
:
cmd
.
SendReminder
,
Frequency
:
cmd
.
Frequency
,
Settings
:
cmd
.
Settings
,
Uid
:
"notifier1"
,
}
err
=
CreateAlertNotificationCommand
(
anotherUidCmd
)
So
(
err
,
ShouldNotBeNil
)
})
Convey
(
"Can save Alert Notification with another name and another uid"
,
func
()
{
anotherUidCmd
:=
&
models
.
CreateAlertNotificationCommand
{
Name
:
"another ops"
,
Type
:
cmd
.
Type
,
OrgId
:
1
,
SendReminder
:
cmd
.
SendReminder
,
Frequency
:
cmd
.
Frequency
,
Settings
:
cmd
.
Settings
,
Uid
:
"notifier2"
,
}
err
=
CreateAlertNotificationCommand
(
anotherUidCmd
)
So
(
err
,
ShouldBeNil
)
})
Convey
(
"Can update alert notification"
,
func
()
{
Convey
(
"Can update alert notification"
,
func
()
{
newCmd
:=
&
models
.
UpdateAlertNotificationCommand
{
newCmd
:=
&
models
.
UpdateAlertNotificationCommand
{
...
@@ -274,12 +301,12 @@ func TestAlertNotificationSQLAccess(t *testing.T) {
...
@@ -274,12 +301,12 @@ func TestAlertNotificationSQLAccess(t *testing.T) {
So
(
CreateAlertNotificationCommand
(
&
otherOrg
),
ShouldBeNil
)
So
(
CreateAlertNotificationCommand
(
&
otherOrg
),
ShouldBeNil
)
Convey
(
"search"
,
func
()
{
Convey
(
"search"
,
func
()
{
query
:=
&
models
.
GetAlertNotificationsToSendQuery
{
query
:=
&
models
.
GetAlertNotifications
WithUid
ToSendQuery
{
Ids
:
[]
int64
{
cmd1
.
Result
.
Id
,
cmd2
.
Result
.
Id
,
112341231
},
Uids
:
[]
string
{
cmd1
.
Result
.
Uid
,
cmd2
.
Result
.
Uid
,
"112341231"
},
OrgId
:
1
,
OrgId
:
1
,
}
}
err
:=
GetAlertNotificationsToSend
(
query
)
err
:=
GetAlertNotifications
WithUid
ToSend
(
query
)
So
(
err
,
ShouldBeNil
)
So
(
err
,
ShouldBeNil
)
So
(
len
(
query
.
Result
),
ShouldEqual
,
3
)
So
(
len
(
query
.
Result
),
ShouldEqual
,
3
)
})
})
...
...
pkg/services/sqlstore/migrations/alert_mig.go
View file @
f132e929
...
@@ -137,4 +137,18 @@ func addAlertMigrations(mg *Migrator) {
...
@@ -137,4 +137,18 @@ func addAlertMigrations(mg *Migrator) {
mg
.
AddMigration
(
"Add for to alert table"
,
NewAddColumnMigration
(
alertV1
,
&
Column
{
mg
.
AddMigration
(
"Add for to alert table"
,
NewAddColumnMigration
(
alertV1
,
&
Column
{
Name
:
"for"
,
Type
:
DB_BigInt
,
Nullable
:
true
,
Name
:
"for"
,
Type
:
DB_BigInt
,
Nullable
:
true
,
}))
}))
mg
.
AddMigration
(
"Add column uid in alert_notification"
,
NewAddColumnMigration
(
alert_notification
,
&
Column
{
Name
:
"uid"
,
Type
:
DB_NVarchar
,
Length
:
40
,
Nullable
:
true
,
}))
mg
.
AddMigration
(
"Update uid column values in alert_notification"
,
new
(
RawSqlMigration
)
.
Sqlite
(
"UPDATE alert_notification SET uid=printf('%09d',id) WHERE uid IS NULL;"
)
.
Postgres
(
"UPDATE alert_notification SET uid=lpad('' || id,9,'0') WHERE uid IS NULL;"
)
.
Mysql
(
"UPDATE alert_notification SET uid=lpad(id,9,'0') WHERE uid IS NULL;"
))
mg
.
AddMigration
(
"Add unique index alert_notification_org_id_uid"
,
NewAddIndexMigration
(
alert_notification
,
&
Index
{
Cols
:
[]
string
{
"org_id"
,
"uid"
},
Type
:
UniqueIndex
,
}))
mg
.
AddMigration
(
"Remove unique index org_id_name"
,
NewDropIndexMigration
(
alert_notification
,
&
Index
{
Cols
:
[]
string
{
"org_id"
,
"name"
},
Type
:
UniqueIndex
,
}))
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment