Skip to content

Commit

Permalink
feat(pkger): add application functionality for the notification rules…
Browse files Browse the repository at this point in the history
… resource
  • Loading branch information
jsteenb2 committed Dec 20, 2019
1 parent 02aec6e commit ed78778
Show file tree
Hide file tree
Showing 12 changed files with 462 additions and 42 deletions.
17 changes: 17 additions & 0 deletions cmd/influx/pkg.go
Original file line number Diff line number Diff line change
Expand Up @@ -790,6 +790,23 @@ func (b *cmdPkgBuilder) printPkgSummary(sum pkger.Summary) {
})
}

if rules := sum.NotificationRules; len(rules) > 0 {
headers := []string{"ID", "Name", "Description", "Every", "Offset", "Endpoint Name", "Endpoint ID", "Endpoint Type"}
tablePrintFn("NOTIFICATION RULES", headers, len(rules), func(i int) []string {
v := rules[i]
return []string{
v.ID.String(),
v.Name,
v.Description,
v.Every,
v.Offset,
v.EndpointName,
v.EndpointID.String(),
v.EndpointType,
}
})
}

if teles := sum.TelegrafConfigs; len(teles) > 0 {
headers := []string{"ID", "Name", "Description"}
tablePrintFn("TELEGRAF CONFIGS", headers, len(teles), func(i int) []string {
Expand Down
3 changes: 2 additions & 1 deletion cmd/influxd/launcher/launcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -844,7 +844,8 @@ func (m *Launcher) run(ctx context.Context) (err error) {
pkger.WithCheckSVC(authorizer.NewCheckService(b.CheckService, authedURMSVC, authedOrgSVC)),
pkger.WithDashboardSVC(authorizer.NewDashboardService(b.DashboardService)),
pkger.WithLabelSVC(authorizer.NewLabelService(b.LabelService)),
pkger.WithNoticationEndpointSVC(authorizer.NewNotificationEndpointService(b.NotificationEndpointService, authedURMSVC, authedOrgSVC)),
pkger.WithNotificationEndpointSVC(authorizer.NewNotificationEndpointService(b.NotificationEndpointService, authedURMSVC, authedOrgSVC)),
pkger.WithNotificationRuleSVC(authorizer.NewNotificationRuleStore(b.NotificationRuleStore, authedURMSVC, authedOrgSVC)),
pkger.WithSecretSVC(authorizer.NewSecretService(b.SecretService)),
pkger.WithTelegrafSVC(authorizer.NewTelegrafConfigService(b.TelegrafService, b.UserResourceMappingService)),
pkger.WithVariableSVC(authorizer.NewVariableService(b.VariableService)),
Expand Down
12 changes: 10 additions & 2 deletions cmd/influxd/launcher/pkger_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func TestLauncher_Pkger(t *testing.T) {
LabelService: l.LabelService(t),
killCount: 2, // hits error on 3rd attempt at creating a mapping
}),
pkger.WithNoticationEndpointSVC(l.NotificationEndpointService(t)),
pkger.WithNotificationEndpointSVC(l.NotificationEndpointService(t)),
pkger.WithTelegrafSVC(l.TelegrafService(t)),
pkger.WithVariableSVC(l.VariableService(t)),
)
Expand Down Expand Up @@ -238,6 +238,14 @@ func TestLauncher_Pkger(t *testing.T) {
assert.Equal(t, influxdb.TaskStatusInactive, string(endpoints[0].NotificationEndpoint.GetStatus()))
hasLabelAssociations(t, endpoints[0].LabelAssociations, 1, "label_1")

require.Len(t, sum1.NotificationRules, 1)
rule := sum1.NotificationRules[0]
assert.NotZero(t, rule.ID)
assert.Equal(t, "rule_0", rule.Name)
assert.Equal(t, pkger.SafeID(endpoints[0].NotificationEndpoint.GetID()), rule.EndpointID)
assert.Equal(t, "http_none_auth_notification_endpoint", rule.EndpointName)
assert.Equal(t, "http", rule.EndpointType)

teles := sum1.TelegrafConfigs
require.Len(t, teles, 1)
assert.NotZero(t, teles[0].TelegrafConfig.ID)
Expand Down Expand Up @@ -473,7 +481,7 @@ spec:
pkger.WithCheckSVC(l.CheckService()),
pkger.WithDashboardSVC(l.DashboardService(t)),
pkger.WithLabelSVC(l.LabelService(t)),
pkger.WithNoticationEndpointSVC(l.NotificationEndpointService(t)),
pkger.WithNotificationEndpointSVC(l.NotificationEndpointService(t)),
pkger.WithTelegrafSVC(l.TelegrafService(t)),
pkger.WithVariableSVC(l.VariableService(t)),
)
Expand Down
54 changes: 46 additions & 8 deletions mock/notification_rule_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,45 +10,83 @@ var _ influxdb.NotificationRuleStore = &NotificationRuleStore{}

// NotificationRuleStore represents a service for managing notification rule data.
type NotificationRuleStore struct {
OrganizationService
UserResourceMappingService
FindNotificationRuleByIDF func(ctx context.Context, id influxdb.ID) (influxdb.NotificationRule, error)
FindNotificationRulesF func(ctx context.Context, filter influxdb.NotificationRuleFilter, opt ...influxdb.FindOptions) ([]influxdb.NotificationRule, int, error)
CreateNotificationRuleF func(ctx context.Context, nr influxdb.NotificationRuleCreate, userID influxdb.ID) error
UpdateNotificationRuleF func(ctx context.Context, id influxdb.ID, nr influxdb.NotificationRuleCreate, userID influxdb.ID) (influxdb.NotificationRule, error)
PatchNotificationRuleF func(ctx context.Context, id influxdb.ID, upd influxdb.NotificationRuleUpdate) (influxdb.NotificationRule, error)
DeleteNotificationRuleF func(ctx context.Context, id influxdb.ID) error
*OrganizationService
*UserResourceMappingService
FindNotificationRuleByIDF func(ctx context.Context, id influxdb.ID) (influxdb.NotificationRule, error)
FindNotificationRuleByIDCalls SafeCount
FindNotificationRulesF func(ctx context.Context, filter influxdb.NotificationRuleFilter, opt ...influxdb.FindOptions) ([]influxdb.NotificationRule, int, error)
FindNotificationRulesCalls SafeCount
CreateNotificationRuleF func(ctx context.Context, nr influxdb.NotificationRuleCreate, userID influxdb.ID) error
CreateNotificationRuleCalls SafeCount
UpdateNotificationRuleF func(ctx context.Context, id influxdb.ID, nr influxdb.NotificationRuleCreate, userID influxdb.ID) (influxdb.NotificationRule, error)
UpdateNotificationRuleCalls SafeCount
PatchNotificationRuleF func(ctx context.Context, id influxdb.ID, upd influxdb.NotificationRuleUpdate) (influxdb.NotificationRule, error)
PatchNotificationRuleCalls SafeCount
DeleteNotificationRuleF func(ctx context.Context, id influxdb.ID) error
DeleteNotificationRuleCalls SafeCount
}

// NewNotificationRuleStore creats a fake notification rules tore.
func NewNotificationRuleStore() *NotificationRuleStore {
return &NotificationRuleStore{
OrganizationService: NewOrganizationService(),
UserResourceMappingService: NewUserResourceMappingService(),
FindNotificationRuleByIDF: func(ctx context.Context, id influxdb.ID) (influxdb.NotificationRule, error) {
return nil, nil
},
FindNotificationRulesF: func(ctx context.Context, f influxdb.NotificationRuleFilter, _ ...influxdb.FindOptions) ([]influxdb.NotificationRule, int, error) {
return nil, 0, nil
},
CreateNotificationRuleF: func(ctx context.Context, nr influxdb.NotificationRuleCreate, userID influxdb.ID) error {
return nil
},
UpdateNotificationRuleF: func(ctx context.Context, id influxdb.ID, nr influxdb.NotificationRuleCreate, userID influxdb.ID) (influxdb.NotificationRule, error) {
return nil, nil
},
PatchNotificationRuleF: func(ctx context.Context, id influxdb.ID, upd influxdb.NotificationRuleUpdate) (influxdb.NotificationRule, error) {
return nil, nil
},
DeleteNotificationRuleF: func(ctx context.Context, id influxdb.ID) error {
return nil
},
}
}

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

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

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

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

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

// DeleteNotificationRule removes a notification rule by ID.
func (s *NotificationRuleStore) DeleteNotificationRule(ctx context.Context, id influxdb.ID) error {
defer s.DeleteNotificationRuleCalls.IncrFn()()
return s.DeleteNotificationRuleF(ctx, id)
}
8 changes: 3 additions & 5 deletions notification/rule/rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,11 @@ var typeToRule = map[string](func() influxdb.NotificationRule){
"http": func() influxdb.NotificationRule { return &HTTP{} },
}

type rawRuleJSON struct {
Typ string `json:"type"`
}

// UnmarshalJSON will convert
func UnmarshalJSON(b []byte) (influxdb.NotificationRule, error) {
var raw rawRuleJSON
var raw struct {
Typ string `json:"type"`
}
if err := json.Unmarshal(b, &raw); err != nil {
return nil, &influxdb.Error{
Msg: "unable to detect the notification type from json",
Expand Down
117 changes: 103 additions & 14 deletions pkger/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/influxdata/influxdb/notification"
icheck "github.com/influxdata/influxdb/notification/check"
"github.com/influxdata/influxdb/notification/endpoint"
"github.com/influxdata/influxdb/notification/rule"
)

// Package kinds.
Expand Down Expand Up @@ -403,9 +404,9 @@ type DiffNotificationRule struct {
Name string `json:"name"`
Description string `json:"description"`

// All these fields represent the relationship of the rule to the endpoint.
EndpointName string `json:"endpointName"`
// These 3 fields represent the relationship of the rule to the endpoint.
EndpointID SafeID `json:"endpointID"`
EndpointName string `json:"endpointName"`
EndpointType string `json:"endpointType"`

Every string `json:"every"`
Expand Down Expand Up @@ -658,9 +659,15 @@ func (s *SummaryNotificationEndpoint) UnmarshalJSON(b []byte) error {
// Summary types for NotificationRules which provide a summary of a pkg notification rule.
type (
SummaryNotificationRule struct {
Name string `json:"name"`
Description string `json:"description"`
EndpointName string `json:"endpointName"`
ID SafeID `json:"id"`
Name string `json:"name"`
Description string `json:"description"`

// These 3 fields represent the relationship of the rule to the endpoint.
EndpointID SafeID `json:"endpointID"`
EndpointName string `json:"endpointName"`
EndpointType string `json:"endpointType"`

Every string `json:"every"`
LabelAssociations []SummaryLabel `json:"labelAssociations"`
Offset string `json:"offset"`
Expand Down Expand Up @@ -1495,6 +1502,7 @@ func (n mapperNotificationEndpoints) Len() int {
}

const (
fieldNotificationRuleChannel = "channel"
fieldNotificationRuleCurrentLevel = "currentLevel"
fieldNotificationRuleEndpointName = "endpointName"
fieldNotificationRuleMessageTemplate = "messageTemplate"
Expand All @@ -1504,19 +1512,38 @@ const (
)

type notificationRule struct {
name string
description string
id influxdb.ID
orgID influxdb.ID
name string

channel string
description string
every time.Duration
msgTemplate string
offset time.Duration
status string
statusRules []struct{ curLvl, prevLvl string }
tagRules []struct{ k, v, op string }

endpointID influxdb.ID
endpointName string
every time.Duration
msgTemplate string
offset time.Duration
status string
statusRules []struct{ curLvl, prevLvl string }
tagRules []struct{ k, v, op string }
endpointType string

labels sortedLabels
}

func (r *notificationRule) Exists() bool {
return false
}

func (r *notificationRule) ID() influxdb.ID {
return r.id
}

func (r *notificationRule) Labels() []*label {
return r.labels
}

func (r *notificationRule) Name() string {
return r.name
}
Expand All @@ -1534,8 +1561,11 @@ func (r *notificationRule) Status() influxdb.Status {

func (r *notificationRule) summarize() SummaryNotificationRule {
return SummaryNotificationRule{
ID: SafeID(r.ID()),
Name: r.Name(),
EndpointID: SafeID(r.endpointID),
EndpointName: r.endpointName,
EndpointType: r.endpointType,
Description: r.description,
Every: r.every.String(),
LabelAssociations: toSummaryLabels(r.labels...),
Expand All @@ -1547,6 +1577,55 @@ func (r *notificationRule) summarize() SummaryNotificationRule {
}
}

func (r *notificationRule) toInfluxRule() influxdb.NotificationRule {
base := rule.Base{
ID: r.ID(),
Name: r.Name(),
Description: r.description,
EndpointID: r.endpointID,
OrgID: r.orgID,
Every: toNotificationDuration(r.every),
Offset: toNotificationDuration(r.offset),
}
for _, sr := range r.statusRules {
var prevLvl *notification.CheckLevel
if lvl := notification.ParseCheckLevel(sr.prevLvl); lvl != notification.Unknown {
prevLvl = &lvl
}
base.StatusRules = append(base.StatusRules, notification.StatusRule{
CurrentLevel: notification.ParseCheckLevel(sr.curLvl),
PreviousLevel: prevLvl,
})
}
for _, tr := range r.tagRules {
op, _ := influxdb.ToOperator(tr.op)
base.TagRules = append(base.TagRules, notification.TagRule{
Tag: influxdb.Tag{
Key: tr.k,
Value: tr.v,
},
Operator: op,
})
}

switch r.endpointType {
case "http":
return &rule.HTTP{Base: base}
case "pagerduty":
return &rule.PagerDuty{
Base: base,
MessageTemplate: r.msgTemplate,
}
case "slack":
return &rule.Slack{
Base: base,
Channel: r.channel,
MessageTemplate: r.msgTemplate,
}
}
return nil
}

func (r *notificationRule) valid() []validationErr {
var vErrs []validationErr
if r.endpointName == "" {
Expand Down Expand Up @@ -1601,7 +1680,7 @@ func (r *notificationRule) valid() []validationErr {

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

type mapperNotificationRules []*notificationRule

func (r mapperNotificationRules) Association(i int) labelAssociater {
return r[i]
}

func (r mapperNotificationRules) Len() int {
return len(r)
}

const (
fieldTelegrafConfig = "config"
)
Expand Down
1 change: 1 addition & 0 deletions pkger/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -699,6 +699,7 @@ func (p *Pkg) graphNotificationRules() *parseErr {
name: r.Name(),
endpointName: r.stringShort(fieldNotificationRuleEndpointName),
description: r.stringShort(fieldDescription),
channel: r.stringShort(fieldNotificationRuleChannel),
every: r.durationShort(fieldEvery),
msgTemplate: r.stringShort(fieldNotificationRuleMessageTemplate),
offset: r.durationShort(fieldOffset),
Expand Down
Loading

0 comments on commit ed78778

Please sign in to comment.