Skip to content

Commit 51ac6d1

Browse files
committed
feat(pkger): add application functionality for the notification rules resource
1 parent 2f4cca9 commit 51ac6d1

15 files changed

+557
-42
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
1. [16212](https://github.com/influxdata/influxdb/pull/16212): Add new kv.ForwardCursor interface
1212
1. [16297](https://github.com/influxdata/influxdb/pull/16297): Add support for notification rule to pkger parser
1313
1. [16298](https://github.com/influxdata/influxdb/pull/16298): Add support for notification rule pkger dry run functionality
14+
1. [16305](https://github.com/influxdata/influxdb/pull/16305): Add support for notification rule pkger apply functionality
1415

1516
### Bug Fixes
1617

cmd/influx/pkg.go

+17
Original file line numberDiff line numberDiff line change
@@ -790,6 +790,23 @@ func (b *cmdPkgBuilder) printPkgSummary(sum pkger.Summary) {
790790
})
791791
}
792792

793+
if rules := sum.NotificationRules; len(rules) > 0 {
794+
headers := []string{"ID", "Name", "Description", "Every", "Offset", "Endpoint Name", "Endpoint ID", "Endpoint Type"}
795+
tablePrintFn("NOTIFICATION RULES", headers, len(rules), func(i int) []string {
796+
v := rules[i]
797+
return []string{
798+
v.ID.String(),
799+
v.Name,
800+
v.Description,
801+
v.Every,
802+
v.Offset,
803+
v.EndpointName,
804+
v.EndpointID.String(),
805+
v.EndpointType,
806+
}
807+
})
808+
}
809+
793810
if teles := sum.TelegrafConfigs; len(teles) > 0 {
794811
headers := []string{"ID", "Name", "Description"}
795812
tablePrintFn("TELEGRAF CONFIGS", headers, len(teles), func(i int) []string {

cmd/influxd/launcher/launcher.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -844,7 +844,8 @@ func (m *Launcher) run(ctx context.Context) (err error) {
844844
pkger.WithCheckSVC(authorizer.NewCheckService(b.CheckService, authedURMSVC, authedOrgSVC)),
845845
pkger.WithDashboardSVC(authorizer.NewDashboardService(b.DashboardService)),
846846
pkger.WithLabelSVC(authorizer.NewLabelService(b.LabelService)),
847-
pkger.WithNoticationEndpointSVC(authorizer.NewNotificationEndpointService(b.NotificationEndpointService, authedURMSVC, authedOrgSVC)),
847+
pkger.WithNotificationEndpointSVC(authorizer.NewNotificationEndpointService(b.NotificationEndpointService, authedURMSVC, authedOrgSVC)),
848+
pkger.WithNotificationRuleSVC(authorizer.NewNotificationRuleStore(b.NotificationRuleStore, authedURMSVC, authedOrgSVC)),
848849
pkger.WithSecretSVC(authorizer.NewSecretService(b.SecretService)),
849850
pkger.WithTelegrafSVC(authorizer.NewTelegrafConfigService(b.TelegrafService, b.UserResourceMappingService)),
850851
pkger.WithVariableSVC(authorizer.NewVariableService(b.VariableService)),

cmd/influxd/launcher/launcher_helpers.go

+4
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,10 @@ func (tl *TestLauncher) NotificationEndpointService(tb testing.TB) *http.Notific
354354
return http.NewNotificationEndpointService(tl.HTTPClient(tb))
355355
}
356356

357+
func (tl *TestLauncher) NotificationRuleService() platform.NotificationRuleStore {
358+
return tl.kvService
359+
}
360+
357361
func (tl *TestLauncher) PkgerService(tb testing.TB) pkger.SVC {
358362
return &http.PkgerService{Client: tl.HTTPClient(tb)}
359363
}

cmd/influxd/launcher/pkger_test.go

+17-2
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ func TestLauncher_Pkger(t *testing.T) {
4747
LabelService: l.LabelService(t),
4848
killCount: 2, // hits error on 3rd attempt at creating a mapping
4949
}),
50-
pkger.WithNoticationEndpointSVC(l.NotificationEndpointService(t)),
50+
pkger.WithNotificationEndpointSVC(l.NotificationEndpointService(t)),
51+
pkger.WithNotificationRuleSVC(l.NotificationRuleService()),
5152
pkger.WithTelegrafSVC(l.TelegrafService(t)),
5253
pkger.WithVariableSVC(l.VariableService(t)),
5354
)
@@ -81,6 +82,12 @@ func TestLauncher_Pkger(t *testing.T) {
8182
require.NoError(t, err)
8283
assert.Empty(t, endpoints)
8384

85+
rules, _, err := l.NotificationRuleService().FindNotificationRules(ctx, influxdb.NotificationRuleFilter{
86+
OrgID: &l.Org.ID,
87+
})
88+
require.NoError(t, err)
89+
assert.Empty(t, rules)
90+
8491
teles, _, err := l.TelegrafService(t).FindTelegrafConfigs(ctx, influxdb.TelegrafConfigFilter{
8592
OrgID: &l.Org.ID,
8693
})
@@ -238,6 +245,14 @@ func TestLauncher_Pkger(t *testing.T) {
238245
assert.Equal(t, influxdb.TaskStatusInactive, string(endpoints[0].NotificationEndpoint.GetStatus()))
239246
hasLabelAssociations(t, endpoints[0].LabelAssociations, 1, "label_1")
240247

248+
require.Len(t, sum1.NotificationRules, 1)
249+
rule := sum1.NotificationRules[0]
250+
assert.NotZero(t, rule.ID)
251+
assert.Equal(t, "rule_0", rule.Name)
252+
assert.Equal(t, pkger.SafeID(endpoints[0].NotificationEndpoint.GetID()), rule.EndpointID)
253+
assert.Equal(t, "http_none_auth_notification_endpoint", rule.EndpointName)
254+
assert.Equal(t, "http", rule.EndpointType)
255+
241256
teles := sum1.TelegrafConfigs
242257
require.Len(t, teles, 1)
243258
assert.NotZero(t, teles[0].TelegrafConfig.ID)
@@ -473,7 +488,7 @@ spec:
473488
pkger.WithCheckSVC(l.CheckService()),
474489
pkger.WithDashboardSVC(l.DashboardService(t)),
475490
pkger.WithLabelSVC(l.LabelService(t)),
476-
pkger.WithNoticationEndpointSVC(l.NotificationEndpointService(t)),
491+
pkger.WithNotificationEndpointSVC(l.NotificationEndpointService(t)),
477492
pkger.WithTelegrafSVC(l.TelegrafService(t)),
478493
pkger.WithVariableSVC(l.VariableService(t)),
479494
)

mock/notification_rule_store.go

+46-8
Original file line numberDiff line numberDiff line change
@@ -10,45 +10,83 @@ var _ influxdb.NotificationRuleStore = &NotificationRuleStore{}
1010

1111
// NotificationRuleStore represents a service for managing notification rule data.
1212
type NotificationRuleStore struct {
13-
OrganizationService
14-
UserResourceMappingService
15-
FindNotificationRuleByIDF func(ctx context.Context, id influxdb.ID) (influxdb.NotificationRule, error)
16-
FindNotificationRulesF func(ctx context.Context, filter influxdb.NotificationRuleFilter, opt ...influxdb.FindOptions) ([]influxdb.NotificationRule, int, error)
17-
CreateNotificationRuleF func(ctx context.Context, nr influxdb.NotificationRuleCreate, userID influxdb.ID) error
18-
UpdateNotificationRuleF func(ctx context.Context, id influxdb.ID, nr influxdb.NotificationRuleCreate, userID influxdb.ID) (influxdb.NotificationRule, error)
19-
PatchNotificationRuleF func(ctx context.Context, id influxdb.ID, upd influxdb.NotificationRuleUpdate) (influxdb.NotificationRule, error)
20-
DeleteNotificationRuleF func(ctx context.Context, id influxdb.ID) error
13+
*OrganizationService
14+
*UserResourceMappingService
15+
FindNotificationRuleByIDF func(ctx context.Context, id influxdb.ID) (influxdb.NotificationRule, error)
16+
FindNotificationRuleByIDCalls SafeCount
17+
FindNotificationRulesF func(ctx context.Context, filter influxdb.NotificationRuleFilter, opt ...influxdb.FindOptions) ([]influxdb.NotificationRule, int, error)
18+
FindNotificationRulesCalls SafeCount
19+
CreateNotificationRuleF func(ctx context.Context, nr influxdb.NotificationRuleCreate, userID influxdb.ID) error
20+
CreateNotificationRuleCalls SafeCount
21+
UpdateNotificationRuleF func(ctx context.Context, id influxdb.ID, nr influxdb.NotificationRuleCreate, userID influxdb.ID) (influxdb.NotificationRule, error)
22+
UpdateNotificationRuleCalls SafeCount
23+
PatchNotificationRuleF func(ctx context.Context, id influxdb.ID, upd influxdb.NotificationRuleUpdate) (influxdb.NotificationRule, error)
24+
PatchNotificationRuleCalls SafeCount
25+
DeleteNotificationRuleF func(ctx context.Context, id influxdb.ID) error
26+
DeleteNotificationRuleCalls SafeCount
27+
}
28+
29+
// NewNotificationRuleStore creats a fake notification rules tore.
30+
func NewNotificationRuleStore() *NotificationRuleStore {
31+
return &NotificationRuleStore{
32+
OrganizationService: NewOrganizationService(),
33+
UserResourceMappingService: NewUserResourceMappingService(),
34+
FindNotificationRuleByIDF: func(ctx context.Context, id influxdb.ID) (influxdb.NotificationRule, error) {
35+
return nil, nil
36+
},
37+
FindNotificationRulesF: func(ctx context.Context, f influxdb.NotificationRuleFilter, _ ...influxdb.FindOptions) ([]influxdb.NotificationRule, int, error) {
38+
return nil, 0, nil
39+
},
40+
CreateNotificationRuleF: func(ctx context.Context, nr influxdb.NotificationRuleCreate, userID influxdb.ID) error {
41+
return nil
42+
},
43+
UpdateNotificationRuleF: func(ctx context.Context, id influxdb.ID, nr influxdb.NotificationRuleCreate, userID influxdb.ID) (influxdb.NotificationRule, error) {
44+
return nil, nil
45+
},
46+
PatchNotificationRuleF: func(ctx context.Context, id influxdb.ID, upd influxdb.NotificationRuleUpdate) (influxdb.NotificationRule, error) {
47+
return nil, nil
48+
},
49+
DeleteNotificationRuleF: func(ctx context.Context, id influxdb.ID) error {
50+
return nil
51+
},
52+
}
2153
}
2254

2355
// FindNotificationRuleByID returns a single telegraf config by ID.
2456
func (s *NotificationRuleStore) FindNotificationRuleByID(ctx context.Context, id influxdb.ID) (influxdb.NotificationRule, error) {
57+
defer s.FindNotificationRuleByIDCalls.IncrFn()()
2558
return s.FindNotificationRuleByIDF(ctx, id)
2659
}
2760

2861
// FindNotificationRules returns a list of notification rules that match filter and the total count of matching notification rules.
2962
// Additional options provide pagination & sorting.
3063
func (s *NotificationRuleStore) FindNotificationRules(ctx context.Context, filter influxdb.NotificationRuleFilter, opt ...influxdb.FindOptions) ([]influxdb.NotificationRule, int, error) {
64+
defer s.FindNotificationRulesCalls.IncrFn()()
3165
return s.FindNotificationRulesF(ctx, filter, opt...)
3266
}
3367

3468
// CreateNotificationRule creates a new notification rule and sets ID with the new identifier.
3569
func (s *NotificationRuleStore) CreateNotificationRule(ctx context.Context, nr influxdb.NotificationRuleCreate, userID influxdb.ID) error {
70+
defer s.CreateNotificationRuleCalls.IncrFn()()
3671
return s.CreateNotificationRuleF(ctx, nr, userID)
3772
}
3873

3974
// UpdateNotificationRule updates a single notification rule.
4075
// Returns the new notification rule after update.
4176
func (s *NotificationRuleStore) UpdateNotificationRule(ctx context.Context, id influxdb.ID, nr influxdb.NotificationRuleCreate, userID influxdb.ID) (influxdb.NotificationRule, error) {
77+
defer s.UpdateNotificationRuleCalls.IncrFn()()
4278
return s.UpdateNotificationRuleF(ctx, id, nr, userID)
4379
}
4480

4581
// PatchNotificationRule updates a single notification rule with changeset.
4682
// Returns the new notification rule after update.
4783
func (s *NotificationRuleStore) PatchNotificationRule(ctx context.Context, id influxdb.ID, upd influxdb.NotificationRuleUpdate) (influxdb.NotificationRule, error) {
84+
defer s.PatchNotificationRuleCalls.IncrFn()()
4885
return s.PatchNotificationRuleF(ctx, id, upd)
4986
}
5087

5188
// DeleteNotificationRule removes a notification rule by ID.
5289
func (s *NotificationRuleStore) DeleteNotificationRule(ctx context.Context, id influxdb.ID) error {
90+
defer s.DeleteNotificationRuleCalls.IncrFn()()
5391
return s.DeleteNotificationRuleF(ctx, id)
5492
}

notification/rule/rule.go

+3-5
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,11 @@ var typeToRule = map[string](func() influxdb.NotificationRule){
1818
"http": func() influxdb.NotificationRule { return &HTTP{} },
1919
}
2020

21-
type rawRuleJSON struct {
22-
Typ string `json:"type"`
23-
}
24-
2521
// UnmarshalJSON will convert
2622
func UnmarshalJSON(b []byte) (influxdb.NotificationRule, error) {
27-
var raw rawRuleJSON
23+
var raw struct {
24+
Typ string `json:"type"`
25+
}
2826
if err := json.Unmarshal(b, &raw); err != nil {
2927
return nil, &influxdb.Error{
3028
Msg: "unable to detect the notification type from json",

pkger/models.go

+103-14
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/influxdata/influxdb/notification"
1616
icheck "github.com/influxdata/influxdb/notification/check"
1717
"github.com/influxdata/influxdb/notification/endpoint"
18+
"github.com/influxdata/influxdb/notification/rule"
1819
)
1920

2021
// Package kinds.
@@ -403,9 +404,9 @@ type DiffNotificationRule struct {
403404
Name string `json:"name"`
404405
Description string `json:"description"`
405406

406-
// All these fields represent the relationship of the rule to the endpoint.
407-
EndpointName string `json:"endpointName"`
407+
// These 3 fields represent the relationship of the rule to the endpoint.
408408
EndpointID SafeID `json:"endpointID"`
409+
EndpointName string `json:"endpointName"`
409410
EndpointType string `json:"endpointType"`
410411

411412
Every string `json:"every"`
@@ -658,9 +659,15 @@ func (s *SummaryNotificationEndpoint) UnmarshalJSON(b []byte) error {
658659
// Summary types for NotificationRules which provide a summary of a pkg notification rule.
659660
type (
660661
SummaryNotificationRule struct {
661-
Name string `json:"name"`
662-
Description string `json:"description"`
663-
EndpointName string `json:"endpointName"`
662+
ID SafeID `json:"id"`
663+
Name string `json:"name"`
664+
Description string `json:"description"`
665+
666+
// These 3 fields represent the relationship of the rule to the endpoint.
667+
EndpointID SafeID `json:"endpointID"`
668+
EndpointName string `json:"endpointName"`
669+
EndpointType string `json:"endpointType"`
670+
664671
Every string `json:"every"`
665672
LabelAssociations []SummaryLabel `json:"labelAssociations"`
666673
Offset string `json:"offset"`
@@ -1495,6 +1502,7 @@ func (n mapperNotificationEndpoints) Len() int {
14951502
}
14961503

14971504
const (
1505+
fieldNotificationRuleChannel = "channel"
14981506
fieldNotificationRuleCurrentLevel = "currentLevel"
14991507
fieldNotificationRuleEndpointName = "endpointName"
15001508
fieldNotificationRuleMessageTemplate = "messageTemplate"
@@ -1504,19 +1512,38 @@ const (
15041512
)
15051513

15061514
type notificationRule struct {
1507-
name string
1508-
description string
1515+
id influxdb.ID
1516+
orgID influxdb.ID
1517+
name string
1518+
1519+
channel string
1520+
description string
1521+
every time.Duration
1522+
msgTemplate string
1523+
offset time.Duration
1524+
status string
1525+
statusRules []struct{ curLvl, prevLvl string }
1526+
tagRules []struct{ k, v, op string }
1527+
1528+
endpointID influxdb.ID
15091529
endpointName string
1510-
every time.Duration
1511-
msgTemplate string
1512-
offset time.Duration
1513-
status string
1514-
statusRules []struct{ curLvl, prevLvl string }
1515-
tagRules []struct{ k, v, op string }
1530+
endpointType string
15161531

15171532
labels sortedLabels
15181533
}
15191534

1535+
func (r *notificationRule) Exists() bool {
1536+
return false
1537+
}
1538+
1539+
func (r *notificationRule) ID() influxdb.ID {
1540+
return r.id
1541+
}
1542+
1543+
func (r *notificationRule) Labels() []*label {
1544+
return r.labels
1545+
}
1546+
15201547
func (r *notificationRule) Name() string {
15211548
return r.name
15221549
}
@@ -1534,8 +1561,11 @@ func (r *notificationRule) Status() influxdb.Status {
15341561

15351562
func (r *notificationRule) summarize() SummaryNotificationRule {
15361563
return SummaryNotificationRule{
1564+
ID: SafeID(r.ID()),
15371565
Name: r.Name(),
1566+
EndpointID: SafeID(r.endpointID),
15381567
EndpointName: r.endpointName,
1568+
EndpointType: r.endpointType,
15391569
Description: r.description,
15401570
Every: r.every.String(),
15411571
LabelAssociations: toSummaryLabels(r.labels...),
@@ -1547,6 +1577,55 @@ func (r *notificationRule) summarize() SummaryNotificationRule {
15471577
}
15481578
}
15491579

1580+
func (r *notificationRule) toInfluxRule() influxdb.NotificationRule {
1581+
base := rule.Base{
1582+
ID: r.ID(),
1583+
Name: r.Name(),
1584+
Description: r.description,
1585+
EndpointID: r.endpointID,
1586+
OrgID: r.orgID,
1587+
Every: toNotificationDuration(r.every),
1588+
Offset: toNotificationDuration(r.offset),
1589+
}
1590+
for _, sr := range r.statusRules {
1591+
var prevLvl *notification.CheckLevel
1592+
if lvl := notification.ParseCheckLevel(sr.prevLvl); lvl != notification.Unknown {
1593+
prevLvl = &lvl
1594+
}
1595+
base.StatusRules = append(base.StatusRules, notification.StatusRule{
1596+
CurrentLevel: notification.ParseCheckLevel(sr.curLvl),
1597+
PreviousLevel: prevLvl,
1598+
})
1599+
}
1600+
for _, tr := range r.tagRules {
1601+
op, _ := influxdb.ToOperator(tr.op)
1602+
base.TagRules = append(base.TagRules, notification.TagRule{
1603+
Tag: influxdb.Tag{
1604+
Key: tr.k,
1605+
Value: tr.v,
1606+
},
1607+
Operator: op,
1608+
})
1609+
}
1610+
1611+
switch r.endpointType {
1612+
case "http":
1613+
return &rule.HTTP{Base: base}
1614+
case "pagerduty":
1615+
return &rule.PagerDuty{
1616+
Base: base,
1617+
MessageTemplate: r.msgTemplate,
1618+
}
1619+
case "slack":
1620+
return &rule.Slack{
1621+
Base: base,
1622+
Channel: r.channel,
1623+
MessageTemplate: r.msgTemplate,
1624+
}
1625+
}
1626+
return nil
1627+
}
1628+
15501629
func (r *notificationRule) valid() []validationErr {
15511630
var vErrs []validationErr
15521631
if r.endpointName == "" {
@@ -1601,7 +1680,7 @@ func (r *notificationRule) valid() []validationErr {
16011680

16021681
var tagErrs []validationErr
16031682
for i, tRule := range r.tagRules {
1604-
if tRule.op != "equal" {
1683+
if _, ok := influxdb.ToOperator(tRule.op); !ok {
16051684
tagErrs = append(tagErrs, validationErr{
16061685
Field: fieldOperator,
16071686
Msg: fmt.Sprintf("must be 1 in [equal]; got=%q", tRule.op),
@@ -1659,6 +1738,16 @@ func toSummaryTagRules(tagRules []struct{ k, v, op string }) []SummaryTagRule {
16591738
return out
16601739
}
16611740

1741+
type mapperNotificationRules []*notificationRule
1742+
1743+
func (r mapperNotificationRules) Association(i int) labelAssociater {
1744+
return r[i]
1745+
}
1746+
1747+
func (r mapperNotificationRules) Len() int {
1748+
return len(r)
1749+
}
1750+
16621751
const (
16631752
fieldTelegrafConfig = "config"
16641753
)

0 commit comments

Comments
 (0)