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 @@
apiVersion
:
1
# alert_notifications:
# - name: default-slack
# - name: default-slack
-temp
# type: slack
# org_
id: 1
# org_
name: Main Org.
# is_default: true
# uid: notifier1
# settings:
# recipient: "XXX"
# token: "xoxb"
...
...
@@ -14,10 +15,11 @@ apiVersion: 1
# - name: default-email
# type: email
# org_id: 1
# uid: notifier2
# is_default: false
# settings:
# addresses: example@example.com
# addresses: example
11111
@example.com
# delete_alert_notifications:
# - name: default-slack
# org_id: 1
# - name: default-email
\ No newline at end of file
# - name: default-slack-temp
# org_name: Main Org.
# uid: notifier1
\ 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
"frequency"
:
"24h"
,
"noDataState"
:
"ok"
,
"notifications"
:
[
{
"
name"
:
"notification-channel-
1"
},
{
"
name"
:
"notification-channel-
2"
},
{
"
uid"
:
"notifier
1"
},
{
"
uid"
:
"notifier
2"
},
]
}
...
...
...
@@ -267,6 +267,7 @@ By default, exporting a dashboard as JSON will use a sequential identifier to re
alert_notifications
:
-
name
:
notification-channel-1
type
:
slack
uid
:
notifier1
# either
org_id
:
2
# or
...
...
@@ -282,6 +283,7 @@ alert_notifications:
delete_alert_notifications
:
-
name
:
notification-channel-1
uid
:
notifier1
# either
org_id
:
2
# or
...
...
pkg/models/alert_notifications.go
View file @
f132e929
...
...
@@ -12,6 +12,7 @@ var (
ErrAlertNotificationStateNotFound
=
errors
.
New
(
"alert notification state not found"
)
ErrAlertNotificationStateVersionConflict
=
errors
.
New
(
"alert notification state update version conflict"
)
ErrAlertNotificationStateAlreadyExist
=
errors
.
New
(
"alert notification state already exists."
)
ErrAlertNotificationFailedGenerateUniqueUid
=
errors
.
New
(
"Failed to generate unique alert notification uid"
)
)
type
AlertNotificationStateType
string
...
...
@@ -24,6 +25,7 @@ var (
type
AlertNotification
struct
{
Id
int64
`json:"id"`
Uid
string
`json:"-"`
OrgId
int64
`json:"-"`
Name
string
`json:"name"`
Type
string
`json:"type"`
...
...
@@ -37,6 +39,7 @@ type AlertNotification struct {
}
type
CreateAlertNotificationCommand
struct
{
Uid
string
`json:"-"`
Name
string
`json:"name" binding:"Required"`
Type
string
`json:"type" binding:"Required"`
SendReminder
bool
`json:"sendReminder"`
...
...
@@ -63,10 +66,28 @@ type UpdateAlertNotificationCommand struct {
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
{
Id
int64
OrgId
int64
}
type
DeleteAlertNotificationWithUidCommand
struct
{
Uid
string
OrgId
int64
}
type
GetAlertNotificationsQuery
struct
{
Name
string
...
...
@@ -76,8 +97,15 @@ type GetAlertNotificationsQuery struct {
Result
*
AlertNotification
}
type
GetAlertNotificationsToSendQuery
struct
{
Ids
[]
int64
type
GetAlertNotificationsWithUidQuery
struct
{
Uid
string
OrgId
int64
Result
*
AlertNotification
}
type
GetAlertNotificationsWithUidToSendQuery
struct
{
Uids
[]
string
OrgId
int64
Result
[]
*
AlertNotification
...
...
pkg/services/alerting/interfaces.go
View file @
f132e929
...
...
@@ -24,7 +24,7 @@ type Notifier interface {
// ShouldNotify checks this evaluation should send an alert notification
ShouldNotify
(
ctx
context
.
Context
,
evalContext
*
EvalContext
,
notificationState
*
models
.
AlertNotificationState
)
bool
GetNotifier
Id
()
int64
GetNotifier
Uid
()
string
GetIsDefault
()
bool
GetSendReminder
()
bool
GetDisableResolveMessage
()
bool
...
...
pkg/services/alerting/notifier.go
View file @
f132e929
...
...
@@ -60,13 +60,13 @@ func (n *notificationService) SendIfNeeded(context *EvalContext) error {
func
(
n
*
notificationService
)
sendAndMarkAsComplete
(
evalContext
*
EvalContext
,
notifierState
*
notifierState
)
error
{
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
()
err
:=
notifier
.
Notify
(
evalContext
)
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
{
...
...
@@ -110,7 +110,7 @@ func (n *notificationService) sendNotifications(evalContext *EvalContext, notifi
for
_
,
notifierState
:=
range
notifierStates
{
err
:=
n
.
sendNotification
(
evalContext
,
notifierState
)
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) {
return
nil
}
func
(
n
*
notificationService
)
getNeededNotifiers
(
orgId
int64
,
notification
Ids
[]
int64
,
evalContext
*
EvalContext
)
(
notifierStateSlice
,
error
)
{
query
:=
&
m
.
GetAlertNotifications
ToSendQuery
{
OrgId
:
orgId
,
Ids
:
notificationI
ds
}
func
(
n
*
notificationService
)
getNeededNotifiers
(
orgId
int64
,
notification
Uids
[]
string
,
evalContext
*
EvalContext
)
(
notifierStateSlice
,
error
)
{
query
:=
&
m
.
GetAlertNotifications
WithUidToSendQuery
{
OrgId
:
orgId
,
Uids
:
notificationUi
ds
}
if
err
:=
bus
.
Dispatch
(
query
);
err
!=
nil
{
return
nil
,
err
...
...
@@ -168,7 +168,7 @@ func (n *notificationService) getNeededNotifiers(orgId int64, notificationIds []
for
_
,
notification
:=
range
query
.
Result
{
not
,
err
:=
InitNotifier
(
notification
)
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
}
...
...
pkg/services/alerting/notifiers/base.go
View file @
f132e929
...
...
@@ -16,7 +16,7 @@ const (
type
NotifierBase
struct
{
Name
string
Type
string
Id
int64
Uid
string
IsDeault
bool
UploadImage
bool
SendReminder
bool
...
...
@@ -34,7 +34,7 @@ func NewNotifierBase(model *models.AlertNotification) NotifierBase {
}
return
NotifierBase
{
Id
:
model
.
I
d
,
Uid
:
model
.
Ui
d
,
Name
:
model
.
Name
,
IsDeault
:
model
.
IsDefault
,
Type
:
model
.
Type
,
...
...
@@ -110,8 +110,8 @@ func (n *NotifierBase) NeedsImage() bool {
return
n
.
UploadImage
}
func
(
n
*
NotifierBase
)
GetNotifier
Id
()
int64
{
return
n
.
I
d
func
(
n
*
NotifierBase
)
GetNotifier
Uid
()
string
{
return
n
.
Ui
d
}
func
(
n
*
NotifierBase
)
GetIsDefault
()
bool
{
...
...
pkg/services/alerting/notifiers/base_test.go
View file @
f132e929
...
...
@@ -173,7 +173,7 @@ func TestBaseNotifier(t *testing.T) {
bJson
:=
simplejson
.
New
()
model
:=
&
m
.
AlertNotification
{
Id
:
1
,
Uid
:
"1"
,
Name
:
"name"
,
Type
:
"email"
,
Settings
:
bJson
,
...
...
pkg/services/alerting/rule.go
View file @
f132e929
...
...
@@ -7,8 +7,6 @@ import (
"strconv"
"time"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/components/simplejson"
m
"github.com/grafana/grafana/pkg/models"
)
...
...
@@ -32,7 +30,7 @@ type Rule struct {
ExecutionErrorState
m
.
ExecutionErrorOption
State
m
.
AlertStateType
Conditions
[]
Condition
Notifications
[]
int64
Notifications
[]
string
StateChanges
int64
}
...
...
@@ -128,22 +126,11 @@ func NewRuleFromDBAlert(ruleDef *m.Alert) (*Rule, error) {
for
_
,
v
:=
range
ruleDef
.
Settings
.
Get
(
"notifications"
)
.
MustArray
()
{
jsonModel
:=
simplejson
.
NewFromAny
(
v
)
id
,
err
:=
jsonModel
.
Get
(
"id"
)
.
Int64
()
uid
,
err
:=
jsonModel
.
Get
(
"uid"
)
.
String
()
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
}
}
cmd
:=
&
m
.
GetAlertNotificationsQuery
{
OrgId
:
ruleDef
.
OrgId
,
Name
:
notificationName
}
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
)
}
model
.
Notifications
=
append
(
model
.
Notifications
,
uid
)
}
...
...
pkg/services/alerting/rule_test.go
View file @
f132e929
...
...
@@ -3,17 +3,11 @@ package alerting
import
(
"testing"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/models"
m
"github.com/grafana/grafana/pkg/models"
.
"github.com/smartystreets/goconvey/convey"
)
var
(
fakeRepo
*
fakeRepository
)
type
FakeCondition
struct
{}
func
(
f
*
FakeCondition
)
Eval
(
context
*
EvalContext
)
(
*
ConditionResult
,
error
)
{
...
...
@@ -78,8 +72,8 @@ func TestAlertRuleModel(t *testing.T) {
}
],
"notifications": [
{"
id": 1134
},
{"
id": 22
}
{"
uid": "1134"
},
{"
uid": "22"
}
]
}
`
...
...
@@ -135,155 +129,6 @@ func TestAlertRuleModel(t *testing.T) {
So
(
err
,
ShouldBeNil
)
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 @@
"noDataState"
:
"no_data"
,
"notifications"
:
[
{
"
id"
:
6
"
uid"
:
"notifier1"
}
]
},
...
...
pkg/services/alerting/testdata/influxdb-alert.json
View file @
f132e929
...
...
@@ -45,7 +45,7 @@
"noDataState"
:
"no_data"
,
"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 {
func
(
dc
*
NotificationProvisioner
)
deleteNotifications
(
notificationToDelete
[]
*
deleteNotificationConfig
)
error
{
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
!=
""
{
getOrg
:=
&
models
.
GetOrgByNameQuery
{
Name
:
notification
.
OrgName
}
...
...
@@ -55,14 +55,14 @@ func (dc *NotificationProvisioner) deleteNotifications(notificationToDelete []*d
}
else
if
notification
.
OrgId
<
0
{
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
{
return
err
}
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
{
return
err
}
...
...
@@ -85,33 +85,40 @@ func (dc *NotificationProvisioner) mergeNotifications(notificationToMerge []*not
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
)
if
err
!=
nil
{
return
err
}
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
{
Uid
:
notification
.
Uid
,
Name
:
notification
.
Name
,
Type
:
notification
.
Type
,
IsDefault
:
notification
.
IsDefault
,
Settings
:
notification
.
SettingsToJson
(),
OrgId
:
notification
.
OrgId
,
DisableResolveMessage
:
notification
.
DisableResolveMessage
,
Frequency
:
notification
.
Frequency
,
SendReminder
:
notification
.
SendReminder
,
}
if
err
:=
bus
.
Dispatch
(
insertCmd
);
err
!=
nil
{
return
err
}
}
else
{
dc
.
log
.
Info
(
"Updating alert notification from configuration"
,
"name"
,
notification
.
Name
)
updateCmd
:=
&
models
.
UpdateAlertNotificationCommand
{
Id
:
cmd
.
Result
.
I
d
,
updateCmd
:=
&
models
.
UpdateAlertNotification
WithUid
Command
{
Uid
:
notification
.
Ui
d
,
Name
:
notification
.
Name
,
Type
:
notification
.
Type
,
IsDefault
:
notification
.
IsDefault
,
Settings
:
notification
.
SettingsToJson
(),
OrgId
:
notification
.
OrgId
,
DisableResolveMessage
:
notification
.
DisableResolveMessage
,
Frequency
:
notification
.
Frequency
,
SendReminder
:
notification
.
SendReminder
,
}
if
err
:=
bus
.
Dispatch
(
updateCmd
);
err
!=
nil
{
return
err
...
...
@@ -130,17 +137,22 @@ func (cfg *notificationsAsConfig) mapToNotificationFromConfig() *notificationsAs
for
_
,
notification
:=
range
cfg
.
Notifications
{
r
.
Notifications
=
append
(
r
.
Notifications
,
&
notificationFromConfig
{
Uid
:
notification
.
Uid
,
OrgId
:
notification
.
OrgId
,
OrgName
:
notification
.
OrgName
,
Name
:
notification
.
Name
,
Type
:
notification
.
Type
,
IsDefault
:
notification
.
IsDefault
,
Settings
:
notification
.
Settings
,
DisableResolveMessage
:
notification
.
DisableResolveMessage
,
Frequency
:
notification
.
Frequency
,
SendReminder
:
notification
.
SendReminder
,
})
}
for
_
,
notification
:=
range
cfg
.
DeleteNotifications
{
r
.
DeleteNotifications
=
append
(
r
.
DeleteNotifications
,
&
deleteNotificationConfig
{
Uid
:
notification
.
Uid
,
OrgId
:
notification
.
OrgId
,
OrgName
:
notification
.
OrgName
,
Name
:
notification
.
Name
,
...
...
pkg/services/provisioning/alert_notifications/config_reader.go
View file @
f132e929
package
alert_notifications
import
(
"fmt"
"io/ioutil"
"os"
"path/filepath"
...
...
@@ -41,7 +42,11 @@ func (cr *configReader) readConfig(path string) ([]*notificationsAsConfig, error
}
cr
.
log
.
Debug
(
"Validating alert notifications"
)
validateOrgIdAndSet
(
notifications
)
if
err
=
validateRequiredField
(
notifications
);
err
!=
nil
{
return
nil
,
err
}
checkOrgIdAndOrgName
(
notifications
)
err
=
validateNotifications
(
notifications
)
if
err
!=
nil
{
...
...
@@ -67,7 +72,7 @@ func (cr *configReader) parseNotificationConfig(path string, file os.FileInfo) (
return
cfg
.
mapToNotificationFromConfig
(),
nil
}
func
validateOrgIdAndSet
(
notifications
[]
*
notificationsAsConfig
)
{
func
checkOrgIdAndOrgName
(
notifications
[]
*
notificationsAsConfig
)
{
for
i
:=
range
notifications
{
for
_
,
notification
:=
range
notifications
[
i
]
.
Notifications
{
if
notification
.
OrgId
<
1
{
...
...
@@ -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
{
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
:
-
name
:
default-slack-notification
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
-
name
:
default-notification-create
type
:
email
uid
:
notifier2
settings
:
addresses
:
example@example.com
org_name
:
Main Org. 2
is_default
:
false
delete_alert_notifications
:
-
name
:
default-slack-notification
org_name
:
Main Org. 1
-
name
:
another-not-default-notification
-
name
:
default-notification-delete
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
:
-
name
:
default-slack-notification
type
:
slack
uid
:
notifier1
org_id
:
2
uid
:
"
notifier1"
is_default
:
true
settings
:
recipient
:
"
XXX"
...
...
@@ -13,21 +15,28 @@ alert_notifications:
settings
:
addresses
:
example@exmaple.com
org_id
:
3
uid
:
"
notifier2"
is_default
:
false
-
name
:
check-unset-is_default-is-false
type
:
slack
org_id
:
3
uid
:
"
notifier3"
settings
:
url
:
https://slack.com
-
name
:
Added notification with whitespaces in name
type
:
email
org_id
:
3
uid
:
"
notifier4"
settings
:
addresses
:
example@exmaple.com
delete_alert_notifications
:
-
name
:
default-slack-notification
org_id
:
2
uid
:
notifier1
-
name
:
deleted-notification-without-orgId
uid
:
"
notifier2"
-
name
:
deleted-notification-with-0-orgId
org_id
:
0
uid
:
"
notifier3"
-
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
:
-
name
:
first-default
type
:
slack
uid
:
notifier1
is_default
:
true
settings
:
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
:
-
name
:
second-default
type
:
email
uid
:
notifier2
is_default
:
true
settings
:
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:
-
name
:
slack-notification-without-url-in-settings
type
:
slack
org_id
:
2
uid
:
notifier1
is_default
:
true
settings
:
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
:
-
name
:
channel1
type
:
slack
settings
:
url
:
http://slack.com
-
name
:
channel2
type
:
email
uid
:
notifier1
org_id
:
1
settings
:
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
:
-
name
:
unknown-notifier
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 {
}
type
deleteNotificationConfig
struct
{
Uid
string
`json:"uid" yaml:"uid"`
Name
string
`json:"name" yaml:"name"`
OrgId
int64
`json:"org_id" yaml:"org_id"`
OrgName
string
`json:"org_name" yaml:"org_name"`
}
type
notificationFromConfig
struct
{
Uid
string
`json:"uid" yaml:"uid"`
OrgId
int64
`json:"org_id" yaml:"org_id"`
OrgName
string
`json:"org_name" yaml:"org_name"`
Name
string
`json:"name" yaml:"name"`
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"`
Settings
map
[
string
]
interface
{}
`json:"settings" yaml:"settings"`
}
...
...
pkg/services/sqlstore/alert_notification.go
View file @
f132e929
...
...
@@ -10,6 +10,7 @@ import (
"github.com/grafana/grafana/pkg/bus"
m
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/util"
)
func
init
()
{
...
...
@@ -17,11 +18,15 @@ func init() {
bus
.
AddHandler
(
"sql"
,
CreateAlertNotificationCommand
)
bus
.
AddHandler
(
"sql"
,
UpdateAlertNotification
)
bus
.
AddHandler
(
"sql"
,
DeleteAlertNotification
)
bus
.
AddHandler
(
"sql"
,
GetAlertNotificationsToSend
)
bus
.
AddHandler
(
"sql"
,
GetAllAlertNotifications
)
bus
.
AddHandlerCtx
(
"sql"
,
GetOrCreateAlertNotificationState
)
bus
.
AddHandlerCtx
(
"sql"
,
SetAlertNotificationStateToCompleteCommand
)
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
{
...
...
@@ -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
{
return
getAlertNotificationInternal
(
query
,
newSession
())
}
func
GetAlertNotificationsWithUid
(
query
*
m
.
GetAlertNotificationsWithUidQuery
)
error
{
return
getAlertNotificationWithUidInternal
(
query
,
newSession
())
}
func
GetAllAlertNotifications
(
query
*
m
.
GetAllAlertNotificationsQuery
)
error
{
results
:=
make
([]
*
m
.
AlertNotification
,
0
)
if
err
:=
x
.
Where
(
"org_id = ?"
,
query
.
OrgId
)
.
Find
(
&
results
);
err
!=
nil
{
...
...
@@ -53,12 +81,13 @@ func GetAllAlertNotifications(query *m.GetAllAlertNotificationsQuery) error {
return
nil
}
func
GetAlertNotifications
ToSend
(
query
*
m
.
GetAlertNotifications
ToSendQuery
)
error
{
func
GetAlertNotifications
WithUidToSend
(
query
*
m
.
GetAlertNotificationsWithUid
ToSendQuery
)
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,
...
...
@@ -77,9 +106,10 @@ func GetAlertNotificationsToSend(query *m.GetAlertNotificationsToSendQuery) erro
sql
.
WriteString
(
` AND ((alert_notification.is_default = ?)`
)
params
=
append
(
params
,
dialect
.
BooleanStr
(
true
))
if
len
(
query
.
Ids
)
>
0
{
sql
.
WriteString
(
` OR alert_notification.id IN (?`
+
strings
.
Repeat
(
",?"
,
len
(
query
.
Ids
)
-
1
)
+
")"
)
for
_
,
v
:=
range
query
.
Ids
{
if
len
(
query
.
Uids
)
>
0
{
sql
.
WriteString
(
` OR alert_notification.uid IN (?`
+
strings
.
Repeat
(
",?"
,
len
(
query
.
Uids
)
-
1
)
+
")"
)
for
_
,
v
:=
range
query
.
Uids
{
params
=
append
(
params
,
v
)
}
}
...
...
@@ -142,16 +172,70 @@ func getAlertNotificationInternal(query *m.GetAlertNotificationsQuery, sess *DBS
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
{
return
inTransaction
(
func
(
sess
*
DBSession
)
error
{
existingQuery
:=
&
m
.
GetAlertNotificationsQuery
{
OrgId
:
cmd
.
OrgId
,
Name
:
cmd
.
Name
}
err
:=
getAlertNotificationInternal
(
existingQuery
,
sess
)
if
cmd
.
Uid
==
""
{
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
{
return
err
}
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
)
}
...
...
@@ -168,6 +252,7 @@ func CreateAlertNotificationCommand(cmd *m.CreateAlertNotificationCommand) error
}
alertNotification
:=
&
m
.
AlertNotification
{
Uid
:
cmd
.
Uid
,
OrgId
:
cmd
.
OrgId
,
Name
:
cmd
.
Name
,
Type
:
cmd
.
Type
,
...
...
@@ -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
{
return
inTransaction
(
func
(
sess
*
DBSession
)
(
err
error
)
{
current
:=
m
.
AlertNotification
{}
...
...
@@ -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
{
return
inTransactionCtx
(
ctx
,
func
(
sess
*
DBSession
)
error
{
version
:=
cmd
.
Version
...
...
pkg/services/sqlstore/alert_notification_test.go
View file @
f132e929
...
...
@@ -220,11 +220,38 @@ func TestAlertNotificationSQLAccess(t *testing.T) {
So
(
cmd
.
Result
.
Type
,
ShouldEqual
,
"email"
)
So
(
cmd
.
Result
.
Frequency
,
ShouldEqual
,
10
*
time
.
Second
)
So
(
cmd
.
Result
.
DisableResolveMessage
,
ShouldBeFalse
)
So
(
cmd
.
Result
.
Uid
,
ShouldNotBeEmpty
)
Convey
(
"Cannot save Alert Notification with the same name"
,
func
()
{
err
=
CreateAlertNotificationCommand
(
cmd
)
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
()
{
newCmd
:=
&
models
.
UpdateAlertNotificationCommand
{
...
...
@@ -274,12 +301,12 @@ func TestAlertNotificationSQLAccess(t *testing.T) {
So
(
CreateAlertNotificationCommand
(
&
otherOrg
),
ShouldBeNil
)
Convey
(
"search"
,
func
()
{
query
:=
&
models
.
GetAlertNotificationsToSendQuery
{
Ids
:
[]
int64
{
cmd1
.
Result
.
Id
,
cmd2
.
Result
.
Id
,
112341231
},
query
:=
&
models
.
GetAlertNotifications
WithUid
ToSendQuery
{
Uids
:
[]
string
{
cmd1
.
Result
.
Uid
,
cmd2
.
Result
.
Uid
,
"112341231"
},
OrgId
:
1
,
}
err
:=
GetAlertNotificationsToSend
(
query
)
err
:=
GetAlertNotifications
WithUid
ToSend
(
query
)
So
(
err
,
ShouldBeNil
)
So
(
len
(
query
.
Result
),
ShouldEqual
,
3
)
})
...
...
pkg/services/sqlstore/migrations/alert_mig.go
View file @
f132e929
...
...
@@ -137,4 +137,18 @@ func addAlertMigrations(mg *Migrator) {
mg
.
AddMigration
(
"Add for to alert table"
,
NewAddColumnMigration
(
alertV1
,
&
Column
{
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